commit c3eb991ed176f0fa143e92874bcbd7b69b2a7f4a
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jul 5 12:17:26 2012 -0400

    	PR c++/50852
    	PR c++/53039
    	* tree.c (strip_typedefs_expr): New.
    	* cp-tree.h: Declare it.
    	* pt.c (convert_template_argument, unify): Use it.
    	* parser.c (cp_parser_template_declaration_after_export): Don't call
    	fixup_template_parms.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 41ca83c..e53f185 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5692,6 +5692,7 @@ extern bool type_has_nontrivial_copy_init	(const_tree);
 extern bool class_tmpl_impl_spec_p		(const_tree);
 extern int zero_init_p				(const_tree);
 extern tree strip_typedefs			(tree);
+extern tree strip_typedefs_expr			(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 027a7b9..4c2167a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -21207,7 +21207,6 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
     {
       /* Parse the template parameters.  */
       parameter_list = cp_parser_template_parameter_list (parser);
-      fixup_template_parms ();
     }
 
   /* Get the deferred access checks from the parameter list.  These
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f618fa5..550a1cb 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6600,7 +6600,7 @@ convert_template_argument (tree parm,
 	   argument specification is valid.  */
 	val = convert_nontype_argument (t, orig_arg, complain);
       else
-	val = orig_arg;
+	val = strip_typedefs_expr (orig_arg);
 
       if (val == NULL_TREE)
 	val = error_mark_node;
@@ -16598,6 +16598,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 	  && !TEMPLATE_PARM_PARAMETER_PACK (parm))
 	return unify_parameter_pack_mismatch (explain_p, parm, arg);
 
+      arg = strip_typedefs_expr (arg);
       TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
       return unify_success (explain_p);
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index a03f845..15effe4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1094,7 +1094,7 @@ cv_unqualified (tree type)
     * If T is a type that needs structural equality
       its TYPE_CANONICAL (T) will be NULL.
     * TYPE_CANONICAL (T) desn't carry type attributes
-      and looses template parameter names.   */
+      and loses template parameter names.   */
 
 tree
 strip_typedefs (tree t)
@@ -1184,6 +1184,16 @@ strip_typedefs (tree t)
 				   TYPENAME_TYPE_FULLNAME (t),
 				   typename_type, tf_none);
       break;
+    case DECLTYPE_TYPE:
+      result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t));
+      if (result == DECLTYPE_TYPE_EXPR (t))
+	return t;
+      else
+	result = (finish_decltype_type
+		  (result,
+		   DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t),
+		   tf_none));
+      break;
     default:
       break;
     }
@@ -1205,6 +1215,186 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
+/* Like strip_typedefs above, but works on expressions, so that in
+
+   template<class T> struct A
+   {
+     typedef T TT;
+     B<sizeof(TT)> b;
+   };
+
+   sizeof(TT) is replaced by sizeof(T).  */
+
+tree
+strip_typedefs_expr (tree t)
+{
+  unsigned i,n;
+  tree r, type, *ops;
+  enum tree_code code;
+
+  if (t == NULL_TREE || t == error_mark_node)
+    return t;
+
+  if (DECL_P (t) || CONSTANT_CLASS_P (t))
+    return t;
+
+  /* Some expressions have type operands, so let's handle types here rather
+     than check TYPE_P in multiple places below.  */
+  if (TYPE_P (t))
+    return strip_typedefs (t);
+
+  code = TREE_CODE (t);
+  switch (code)
+    {
+    case IDENTIFIER_NODE:
+    case TEMPLATE_PARM_INDEX:
+    case OVERLOAD:
+    case BASELINK:
+    case ARGUMENT_PACK_SELECT:
+      return t;
+
+    case TRAIT_EXPR:
+      {
+	tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t));
+	tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t));
+	if (type1 == TRAIT_EXPR_TYPE1 (t)
+	    && type2 == TRAIT_EXPR_TYPE2 (t))
+	  return t;
+	r = copy_node (t);
+	TRAIT_EXPR_TYPE1 (t) = type1;
+	TRAIT_EXPR_TYPE2 (t) = type2;
+	return r;
+      }
+
+    case TREE_LIST:
+      {
+	VEC(tree,gc) *vec = make_tree_vector ();
+	bool changed = false;
+	tree it;
+	for (it = t; it; it = TREE_CHAIN (it))
+	  {
+	    tree val = strip_typedefs_expr (TREE_VALUE (t));
+	    VEC_safe_push (tree, gc, vec, val);
+	    if (val != TREE_VALUE (t))
+	      changed = true;
+	    gcc_assert (TREE_PURPOSE (it) == NULL_TREE);
+	  }
+	if (changed)
+	  {
+	    r = NULL_TREE;
+	    FOR_EACH_VEC_ELT_REVERSE (tree, vec, i, it)
+	      r = tree_cons (NULL_TREE, it, r);
+	  }
+	else
+	  r = t;
+	release_tree_vector (vec);
+	return r;
+      }
+
+    case TREE_VEC:
+      {
+	bool changed = false;
+	VEC(tree,gc)* vec = make_tree_vector ();
+	n = TREE_VEC_LENGTH (t);
+	VEC_reserve (tree, gc, vec, n);
+	for (i = 0; i < n; ++i)
+	  {
+	    tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i));
+	    VEC_quick_push (tree, vec, op);
+	    if (op != TREE_VEC_ELT (t, i))
+	      changed = true;
+	  }
+	if (changed)
+	  {
+	    r = copy_node (t);
+	    for (i = 0; i < n; ++i)
+	      TREE_VEC_ELT (r, i) = VEC_index (tree, vec, i);
+	  }
+	else
+	  r = t;
+	release_tree_vector (vec);
+	return r;
+      }
+
+    case CONSTRUCTOR:
+      {
+	bool changed = false;
+	VEC(constructor_elt,gc) *vec
+	  = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
+	n = CONSTRUCTOR_NELTS (t);
+	type = strip_typedefs (TREE_TYPE (t));
+	for (i = 0; i < n; ++i)
+	  {
+	    constructor_elt *e = VEC_index (constructor_elt, vec, i);
+	    tree op = strip_typedefs_expr (e->value);
+	    if (op != e->value)
+	      {
+		changed = true;
+		e->value = op;
+	      }
+	    gcc_checking_assert (e->index == strip_typedefs_expr (e->index));
+	  }
+
+	if (!changed && type == TREE_TYPE (t))
+	  {
+	    VEC_free (constructor_elt, gc, vec);
+	    return t;
+	  }
+	else
+	  {
+	    r = copy_node (t);
+	    TREE_TYPE (r) = type;
+	    CONSTRUCTOR_ELTS (r) = vec;
+	    return r;
+	  }
+      }
+
+    case LAMBDA_EXPR:
+      gcc_unreachable ();
+
+    default:
+      break;
+    }
+
+  gcc_assert (EXPR_P (t));
+
+  n = TREE_OPERAND_LENGTH (t);
+  ops = XALLOCAVEC (tree, n);
+  type = TREE_TYPE (t);
+
+  switch (code)
+    {
+    CASE_CONVERT:
+    case IMPLICIT_CONV_EXPR:
+    case DYNAMIC_CAST_EXPR:
+    case STATIC_CAST_EXPR:
+    case CONST_CAST_EXPR:
+    case REINTERPRET_CAST_EXPR:
+    case CAST_EXPR:
+    case NEW_EXPR:
+      type = strip_typedefs (type);
+      /* fallthrough */
+
+    default:
+      for (i = 0; i < n; ++i)
+	ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i));
+      break;
+    }
+
+  /* If nothing changed, return t.  */
+  for (i = 0; i < n; ++i)
+    if (ops[i] != TREE_OPERAND (t, i))
+      break;
+  if (i == n && type == TREE_TYPE (t))
+    return t;
+
+  r = copy_node (t);
+  TREE_TYPE (r) = type;
+  for (i = 0; i < n; ++i)
+    TREE_OPERAND (r, i) = ops[i];
+  return r;
+}
+
 /* Makes a copy of BINFO and TYPE, which is to be inherited into a
    graph dominated by T.  If BINFO is NULL, TYPE is a dependent base,
    and we do a shallow copy.  If BINFO is non-NULL, we do a deep copy.
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic133.C b/gcc/testsuite/g++.dg/cpp0x/variadic133.C
new file mode 100644
index 0000000..0265f09
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic133.C
@@ -0,0 +1,46 @@
+// PR c++/53039
+// { dg-do compile { target c++11 } }
+
+template <class, class>
+struct is_convertible
+{
+  static const bool value = true;
+};
+
+template<bool, class T>
+struct enable_if
+{
+  typedef T type;
+};
+
+template <bool...>
+struct Xs
+{
+  static const bool value = true;
+};
+
+template<typename... BTs>
+  class BType
+    {
+      template <typename... BUs,
+        typename enable_if<
+               Xs<is_convertible<BUs, BTs>::value...>::value,
+               bool>::type = false>
+        void fooX(BUs&&...);
+    };
+
+template <typename... ATs>
+  struct AType
+    {
+      template <typename... AUs,
+    typename enable_if<
+               Xs<is_convertible<AUs, ATs>::value...>::value,
+               bool>::type = false>
+        void foo(AUs&&...);
+    };
+
+int main()
+{
+  AType<int, int> t;
+  t.foo(1, 1);
+}
diff --git a/gcc/testsuite/g++.dg/template/param1.C b/gcc/testsuite/g++.dg/template/param1.C
index a8c3791..e378473 100644
--- a/gcc/testsuite/g++.dg/template/param1.C
+++ b/gcc/testsuite/g++.dg/template/param1.C
@@ -2,11 +2,11 @@
 // Origin: Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 // { dg-do compile }
 
-template<int> struct A // { dg-error "declaration" }
+template<int> struct A
 {
   A();
 };
 
-template<int N, char> A<N>::A() {}  // { dg-error "invalid use of incomplete type" }
+template<int N, char> A<N>::A() {}  // { dg-error "got 2 template parameters|1 required" }
 
 A<0> a;
diff --git a/gcc/testsuite/g++.dg/template/typedef39.C b/gcc/testsuite/g++.dg/template/typedef39.C
new file mode 100644
index 0000000..71d8bdb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef39.C
@@ -0,0 +1,15 @@
+// PR c++/50852
+
+template<int d> class A;
+template<class T> struct B {typedef int K;typedef int L;};
+template<class U,class V> struct C
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W;	// { dg-error "not a member" }
+};
+template<class U,int d> struct D
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W;	// the error should really be on this line
+};
+template class D<B<A<1> >,3>;

commit ae4dc4fc1a5b7665277c1aaec0bd2ec7a00889e8
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jul 5 12:42:35 2012 -0400

    	* cp-tree.h (TEMPLATE_PARM_NUM_SIBLINGS): Remove.
    	(struct template_parm_index_s): Remove num_siblings.
    	* pt.c (fixup_template_parms, fixup_template_parm_index): Remove.
    	(fixup_template_type_parm_type): Remove.
    	(build_template_parm_index): Remove num_siblings parm.
    	(process_template_parm): Likewise.
    	* parser.c (cp_parser_template_parameter_list): Adjust.
    	* tree.c (cp_tree_equal): Don't compare num_siblings.
    	* typeck.c (comp_template_parms_position): Likewise.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e53f185..0b2b234 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -249,7 +249,6 @@ struct GTY(()) template_parm_index_s {
   int index;
   int level;
   int orig_level;
-  int num_siblings;
   tree decl;
 };
 typedef struct template_parm_index_s template_parm_index;
@@ -4523,9 +4522,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
 	((template_parm_index*)TEMPLATE_PARM_INDEX_CHECK (NODE))
 #define TEMPLATE_PARM_IDX(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->index)
 #define TEMPLATE_PARM_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->level)
-/* The Number of sibling parms this template parm has.  */
-#define TEMPLATE_PARM_NUM_SIBLINGS(NODE) \
-  (TEMPLATE_PARM_INDEX_CAST (NODE)->num_siblings)
 #define TEMPLATE_PARM_DESCENDANTS(NODE) (TREE_CHAIN (NODE))
 #define TEMPLATE_PARM_ORIG_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->orig_level)
 #define TEMPLATE_PARM_DECL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->decl)
@@ -5316,9 +5312,8 @@ extern void append_type_to_template_for_access_check (tree, tree, tree,
 extern tree splice_late_return_type		(tree, tree);
 extern bool is_auto				(const_tree);
 extern tree process_template_parm		(tree, location_t, tree, 
-						 bool, bool, unsigned);
+						 bool, bool);
 extern tree end_template_parm_list		(tree);
-void fixup_template_parms (void);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
 extern bool check_default_tmpl_args             (tree, tree, int, int, int);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4c2167a..1428a26 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11993,8 +11993,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-						is_parameter_pack,
-						0);
+						is_parameter_pack);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 550a1cb..e07a362 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -147,7 +147,7 @@ static tree convert_template_argument (tree, tree, tree,
 static int for_each_template_parm (tree, tree_fn_t, void*,
 				   struct pointer_set_t*, bool);
 static tree expand_template_argument_pack (tree);
-static tree build_template_parm_index (int, int, int, int, tree, tree);
+static tree build_template_parm_index (int, int, int, tree, tree);
 static bool inline_needs_template_parms (tree);
 static void push_inline_template_parms_recursive (tree, int);
 static tree retrieve_local_specialization (tree);
@@ -203,8 +203,6 @@ static tree listify_autos (tree, tree);
 static tree template_parm_to_arg (tree t);
 static bool arg_from_parm_pack_p (tree, tree);
 static tree current_template_args (void);
-static tree fixup_template_type_parm_type (tree, int);
-static tree fixup_template_parm_index (tree, tree, int);
 static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
@@ -3407,14 +3405,12 @@ check_template_shadow (tree decl)
 }
 
 /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
-   ORIG_LEVEL, DECL, and TYPE.  NUM_SIBLINGS is the total number of
-   template parameters.  */
+   ORIG_LEVEL, DECL, and TYPE.  */
 
 static tree
 build_template_parm_index (int index,
 			   int level,
 			   int orig_level,
-			   int num_siblings,
 			   tree decl,
 			   tree type)
 {
@@ -3422,7 +3418,6 @@ build_template_parm_index (int index,
   TEMPLATE_PARM_IDX (t) = index;
   TEMPLATE_PARM_LEVEL (t) = level;
   TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level;
-  TEMPLATE_PARM_NUM_SIBLINGS (t) = num_siblings;
   TEMPLATE_PARM_DECL (t) = decl;
   TREE_TYPE (t) = type;
   TREE_CONSTANT (t) = TREE_CONSTANT (decl);
@@ -3488,7 +3483,6 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
       t = build_template_parm_index (TEMPLATE_PARM_IDX (index),
 				     TEMPLATE_PARM_LEVEL (index) - levels,
 				     TEMPLATE_PARM_ORIG_LEVEL (index),
-				     TEMPLATE_PARM_NUM_SIBLINGS (index),
 				     decl, type);
       TEMPLATE_PARM_DESCENDANTS (index) = t;
       TEMPLATE_PARM_PARAMETER_PACK (t) 
@@ -3516,8 +3510,7 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
 
 tree
 process_template_parm (tree list, location_t parm_loc, tree parm,
-		       bool is_non_type, bool is_parameter_pack,
-		       unsigned num_template_parms)
+		       bool is_non_type, bool is_parameter_pack)
 {
   tree decl = 0;
   tree defval;
@@ -3592,7 +3585,6 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
       DECL_INITIAL (parm) = DECL_INITIAL (decl)
 	= build_template_parm_index (idx, processing_template_decl,
 				     processing_template_decl,
-				     num_template_parms,
 				     decl, TREE_TYPE (parm));
 
       TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)) 
@@ -3626,7 +3618,6 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
       TEMPLATE_TYPE_PARM_INDEX (t)
 	= build_template_parm_index (idx, processing_template_decl,
 				     processing_template_decl,
-				     num_template_parms,
 				     decl, TREE_TYPE (parm));
       TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
       TYPE_CANONICAL (t) = canonical_type_parameter (t);
@@ -3666,305 +3657,6 @@ end_template_parm_list (tree parms)
   return saved_parmlist;
 }
 
-/* Create a new type almost identical to TYPE but which has the
-   following differences:
-
-     1/ T has a new TEMPLATE_PARM_INDEX that carries the new number of
-     template sibling parameters of T.
-
-     2/ T has a new canonical type that matches the new number
-     of sibling parms.
-
-     3/ From now on, T is going to be what lookups referring to the
-     name of TYPE will return. No lookup should return TYPE anymore.
-
-   NUM_PARMS is the new number of sibling parms TYPE belongs to.
-
-   This is a subroutine of fixup_template_parms.  */
-
-static tree
-fixup_template_type_parm_type (tree type, int num_parms)
-{
-  tree orig_idx = TEMPLATE_TYPE_PARM_INDEX (type), idx;
-  tree t;
-  /* This is the decl which name is inserted into the symbol table for
-     the template parm type. So whenever we lookup the type name, this
-     is the DECL we get.  */
-  tree decl;
-
-  /* Do not fix up the type twice.  */
-  if (orig_idx && TEMPLATE_PARM_NUM_SIBLINGS (orig_idx) != 0)
-    return type;
-
-  t = copy_type (type);
-  decl = TYPE_NAME (t);
-
-  TYPE_MAIN_VARIANT (t) = t;
-  TYPE_NEXT_VARIANT (t)= NULL_TREE;
-  TYPE_POINTER_TO (t) = 0;
-  TYPE_REFERENCE_TO (t) = 0;
-
-  idx = build_template_parm_index (TEMPLATE_PARM_IDX (orig_idx),
-				   TEMPLATE_PARM_LEVEL (orig_idx),
-				   TEMPLATE_PARM_ORIG_LEVEL (orig_idx),
-				   num_parms,
-				   decl, t);
-  TEMPLATE_PARM_DESCENDANTS (idx) = TEMPLATE_PARM_DESCENDANTS (orig_idx);
-  TEMPLATE_PARM_PARAMETER_PACK (idx) = TEMPLATE_PARM_PARAMETER_PACK (orig_idx);
-  TEMPLATE_TYPE_PARM_INDEX (t) = idx;
-
-  TYPE_STUB_DECL (t) = decl;
-  TEMPLATE_TYPE_DECL (t) = decl;
-  if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
-    TREE_TYPE (DECL_TEMPLATE_RESULT  (decl)) = t;
-
-  /* Update the type associated to the type name stored in the symbol
-     table. Now, whenever the type name is looked up, the resulting
-     type is properly fixed up.  */
-  TREE_TYPE (decl) = t;
-
-  TYPE_CANONICAL (t) = canonical_type_parameter (t);
-
-  return t;
-}
-
-/* Create and return a new TEMPLATE_PARM_INDEX that is almost
-   identical to I, but that is fixed up as to:
-
-   1/ carry the number of sibling parms (NUM_PARMS) of the template
-   parm represented by I.
-
-   2/ replace all references to template parm types declared before I
-   (in the same template parm list as I) by references to template
-   parm types contained in ARGS. ARGS should contain the list of
-   template parms that have been fixed up so far, in a form suitable
-   to be passed to tsubst.
-
-   This is a subroutine of fixup_template_parms.  */
-
-static tree
-fixup_template_parm_index (tree i, tree args, int num_parms)
-{
-  tree index, decl, type;
-
-  if (i == NULL_TREE
-      || TREE_CODE (i) != TEMPLATE_PARM_INDEX
-      /* Do not fix up the index twice.  */
-      || (TEMPLATE_PARM_NUM_SIBLINGS (i) != 0))
-    return i;
-
-  decl = TEMPLATE_PARM_DECL (i);
-  type = TREE_TYPE (decl);
-
-  index = build_template_parm_index (TEMPLATE_PARM_IDX (i),
-				     TEMPLATE_PARM_LEVEL (i),
-				     TEMPLATE_PARM_ORIG_LEVEL (i),
-				     num_parms,
-				     decl, type);
-
-  TEMPLATE_PARM_DESCENDANTS (index) = TEMPLATE_PARM_DESCENDANTS (i);
-  TEMPLATE_PARM_PARAMETER_PACK (index) = TEMPLATE_PARM_PARAMETER_PACK (i);
-
-  type = tsubst (type, args, tf_none, NULL_TREE);
-  
-  TREE_TYPE (decl) = type;
-  TREE_TYPE (index) = type;
-
-  return index;
-}
-
-/* 
-   This is a subroutine of fixup_template_parms.
-
-   It computes the canonical type of the type of the template
-   parameter PARM_DESC and update all references to that type so that
-   they use the newly computed canonical type. No access check is
-   performed during the fixup. PARM_DESC is a TREE_LIST which
-   TREE_VALUE is the template parameter and its TREE_PURPOSE is the
-   default argument of the template parm if any. IDX is the index of
-   the template parameter, starting at 0. NUM_PARMS is the number of
-   template parameters in the set PARM_DESC belongs to. ARGLIST is a
-   TREE_VEC containing the full set of template parameters in a form
-   suitable to be passed to substs functions as their ARGS
-   argument. This is what current_template_args returns for a given
-   template. The innermost vector of args in ARGLIST is the set of
-   template parms that have been fixed up so far. This function adds
-   the fixed up parameter into that vector.  */
-
-static void
-fixup_template_parm (tree parm_desc,
-		     int idx,
-		     int num_parms,
-		     tree arglist)
-{
-  tree parm = TREE_VALUE (parm_desc);
-  tree fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
-
-  push_deferring_access_checks (dk_no_check);
-
-  if (TREE_CODE (parm) == TYPE_DECL)
-    {
-      /* PARM is a template type parameter. Fix up its type, add
-	 the fixed-up template parm to the vector of fixed-up
-	 template parms so far, and substitute the fixed-up
-	 template parms into the default argument of this
-	 parameter.  */
-      tree t =
-	fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
-      TREE_TYPE (parm) = t;
-
-      TREE_VEC_ELT (fixedup_args, idx) = template_parm_to_arg (parm_desc);
-    }
-  else if (TREE_CODE (parm) == TEMPLATE_DECL)
-    {
-      /* PARM is a template template parameter. This is going to
-	 be interesting.  */
-      tree tparms, targs, innermost_args, t;
-      int j;
-
-      /* First, fix up the parms of the template template parm
-	 because the parms are involved in defining the new canonical
-	 type of the template template parm.  */
-
-      /* So we need to substitute the template parm types that have
-	 been fixed up so far into the template parms of this template
-	 template parm. E.g, consider this:
-
-	 template<class T, template<T u> class TT> class S;
-
-	 In this case we want to substitute T into the
-	 template parameters of TT.
-
-	 So let's walk the template parms of PARM here, and
-	 tsubst ARGLIST into into each of the template
-	 parms.   */
-
-      /* For this substitution we need to build the full set of
-	 template parameters and use that as arguments for the
-	 tsubsting function.  */
-      tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm));
-
-      /* This will contain the innermost parms of PARM into which
-	 we have substituted so far.  */
-      innermost_args = make_tree_vec (TREE_VEC_LENGTH (tparms));
-      targs = add_to_template_args (arglist, innermost_args);
-      for (j = 0; j < TREE_VEC_LENGTH (tparms); ++j)
-	{
-	  tree parameter;
-
-	  parameter = TREE_VEC_ELT (tparms, j);
-
-	  /* INNERMOST_ARGS needs to have at least the same number
-	     of elements as the index PARAMETER, ortherwise
-	     tsubsting into PARAMETER will result in partially
-	     instantiating it, reducing its tempate parm
-	     level. Let's tactically fill INNERMOST_ARGS for that
-	     purpose.  */
-	  TREE_VEC_ELT (innermost_args, j) =
-	    template_parm_to_arg (parameter);
-
-	  fixup_template_parm (parameter, j,
-			       TREE_VEC_LENGTH (tparms),
-			       targs);
-	}
-
-      /* Now fix up the type of the template template parm.  */
-
-      t = fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
-      TREE_TYPE (parm) = t;
-
-      TREE_VEC_ELT (fixedup_args, idx) =
-	template_parm_to_arg (parm_desc);
-    }
-  else if (TREE_CODE (parm) == PARM_DECL)
-    {
-      /* PARM is a non-type template parameter. We need to:
-
-       * Fix up its TEMPLATE_PARM_INDEX to make it carry the
-       proper number of sibling parameters.
-
-       * Make lookups of the template parameter return a reference
-       to the fixed-up index. No lookup should return references
-       to the former index anymore.
-
-       * Substitute the template parms that got fixed up so far
-
-       * into the type of PARM.  */
-
-      tree index = DECL_INITIAL (parm);
-
-      /* PUSHED_DECL is the decl added to the symbol table with
-	 the name of the parameter. E,g:
-	     
-	 template<class T, T u> //#0
-	 auto my_function(T t) -> decltype(u); //#1
-
-	 Here, when looking up u at //#1, we get the decl of u
-	 resulting from the declaration in #0. This is what
-	 PUSHED_DECL is. We need to replace the reference to the
-	 old TEMPLATE_PARM_INDEX carried by PUSHED_DECL by the
-	 fixed-up TEMPLATE_PARM_INDEX.  */
-      tree pushed_decl = TEMPLATE_PARM_DECL (index);
-
-      /* Let's fix up the TEMPLATE_PARM_INDEX then. Note that we must
-	 fixup the type of PUSHED_DECL as well and luckily
-	 fixup_template_parm_index does it for us too.  */
-      tree fixed_up_index =
-	fixup_template_parm_index (index, arglist, num_parms);
-
-      DECL_INITIAL (pushed_decl) = DECL_INITIAL (parm) = fixed_up_index;
-
-      /* Add this fixed up PARM to the template parms we've fixed
-	 up so far and use that to substitute the fixed-up
-	 template parms into the type of PARM.  */
-      TREE_VEC_ELT (fixedup_args, idx) =
-	template_parm_to_arg (parm_desc);
-      TREE_TYPE (parm) = tsubst (TREE_TYPE (parm), arglist,
-				 tf_none, NULL_TREE);
-    }
-
-  TREE_PURPOSE (parm_desc) =
-    tsubst_template_arg (TREE_PURPOSE (parm_desc),
-			 arglist, tf_none, parm);
-
-  pop_deferring_access_checks ();
-}
-
-/* Walk the current template parms and properly compute the canonical
-   types of the dependent types created during
-   cp_parser_template_parameter_list.  */
-
-void
-fixup_template_parms (void)
-{
-  tree arglist;
-  tree parameter_vec;
-  tree fixedup_args;
-  int i, num_parms;
-
-  parameter_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
-  if (parameter_vec == NULL_TREE)
-    return;
-
-  num_parms = TREE_VEC_LENGTH (parameter_vec);
-
-  /* This vector contains the current innermost template parms that
-     have been fixed up so far.  The form of FIXEDUP_ARGS is suitable
-     to be passed to tsubst* functions as their ARGS argument.  */
-  fixedup_args = make_tree_vec (num_parms);
-
-  /* This vector contains the full set of template parms in a form
-     suitable to be passed to substs functions as their ARGS
-     argument.  */
-  arglist = current_template_args ();
-  arglist = add_outermost_template_args (arglist, fixedup_args);
-
-  /* Let's do the proper fixup now.  */
-  for (i = 0; i < num_parms; ++i)
-    fixup_template_parm (TREE_VEC_ELT (parameter_vec, i),
-			 i, num_parms, arglist);
-}
-
 /* end_template_decl is called after a template declaration is seen.  */
 
 void
@@ -20289,7 +19981,7 @@ make_auto (void)
   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,
-     0, TYPE_NAME (au), NULL_TREE);
+     TYPE_NAME (au), NULL_TREE);
   TYPE_CANONICAL (au) = canonical_type_parameter (au);
   DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
   SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 15effe4..01bc483 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2568,9 +2568,6 @@ cp_tree_equal (tree t1, tree t2)
 				BASELINK_FUNCTIONS (t2)));
 
     case TEMPLATE_PARM_INDEX:
-      if (TEMPLATE_PARM_NUM_SIBLINGS (t1)
-	  != TEMPLATE_PARM_NUM_SIBLINGS (t2))
-	return false;
       return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
 	      && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
 	      && (TEMPLATE_PARM_PARAMETER_PACK (t1)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 3bc3ead..508e8fb 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1140,12 +1140,6 @@ comp_template_parms_position (tree t1, tree t2)
   index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
   index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
 
-  /* If T1 and T2 belong to template parm lists of different size,
-     let's assume they are different.  */
-  if (TEMPLATE_PARM_NUM_SIBLINGS (index1)
-      != TEMPLATE_PARM_NUM_SIBLINGS (index2))
-    return false;
-
   /* Then compare their relative position.  */
   if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
       || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
