public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Dodji Seketeli] Patch PR c++/45200
@ 2010-08-11 18:30 Dodji Seketeli
  2010-08-11 21:04 ` Jason Merrill
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-08-11 18:30 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 64 bytes --]


Sorry, I previously forwarded this to the wrong mailing list.


[-- Attachment #2: Type: message/rfc822, Size: 4012 bytes --]

From: Dodji Seketeli <dodji@redhat.com>
To: Jason Merrill <jason@redhat.com>
Cc: GCC Development <gcc@gcc.gnu.org>
Subject: Patch PR c++/45200
Date: Wed, 11 Aug 2010 15:48:11 +0200
Message-ID: <m3iq3hp8f8.fsf@redhat.com>

Hello,

In the example accompanying the patch below we consider that the
types

     forward_as_lref<typenameseq::seq_type>

at line marked with //#0 and

     forward_as_lref<typename remove_reference<Seq>::type::seq_type>

at the line marked with //#1 should compare equal. And I believe that
is correct[1].

It follows that during the instantiantion of apply<reverse_view>,
lookup_class_template looks up an instantiation for
forward_as_lref<typename remove_reference<Seq>::type::seq_type>
and returns forward_as_lref<typenameseq::seq_type>. Then the
tsubst'ing of forward_as_lref<typenameseq::seq_type> in the
context of template<typename Seq> struct apply fails because it
tries to reuse the typedef seq that was defined in the
incompatible context template<typename Seq, typename N> struct
apply1.

This case seems to argue for stripping typedefs from the
TYPE_CONTEXT of TYPENAME_TYPEs when they are passed as template
arguments. I refrained from doing it before because I thought
that incompatible_dependent_types_p would be enough to handle all
comparisons involving dependent typedefs.

[1]: This is based on the resolution of PR c++/43800 at
http://gcc.gnu.org/ml/gcc-patches/2010-04/msg01241.html

Tested on x86_64-unknown-linux-gnu against trunk and the 4.5
branch. OK to commit to both branches?

commit d9a0f93c1fda1d97cda5747003de84edd3812bda
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Aug 9 23:12:39 2010 +0200

    Fix PR c++/45200

    gcc/cp/Changelog:
    	PR c++/45200
    	* tree.c (strip_typedefs): Strip typedefs from the context of
    	TYPENAME_TYPEs.

    gcc/testsuite/ChangeLog:
    	PR c++/45200
    	* g++.dg/template/typedef34.C: New test.

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 450b9e8..6b2aab0 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1046,6 +1046,11 @@ strip_typedefs (tree t)
 					    TYPE_RAISES_EXCEPTIONS (t));
       }
       break;
+    case TYPENAME_TYPE:
+      result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t)),
+				   TYPENAME_TYPE_FULLNAME (t),
+				   typename_type, tf_none);
+      break;
     default:
       break;
     }
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 484d299..a506053 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1212,7 +1212,7 @@ incompatible_dependent_types_p (tree t1, tree t2)
 
   if (!t1_typedef_variant_p || !t2_typedef_variant_p)
     /* Either T1 or T2 is not a typedef so we cannot compare the
-       the template parms of the typedefs of T1 and T2.
+       template parms of the typedefs of T1 and T2.
        At this point, if the main variant type of T1 and T2 are equal
        it means the two types can't be incompatible, from the perspective
        of this function.  */
diff --git a/gcc/testsuite/g++.dg/template/typedef34.C b/gcc/testsuite/g++.dg/template/typedef34.C
new file mode 100644
index 0000000..9bb4460
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef34.C
@@ -0,0 +1,37 @@
+// Origin PR c++/45200
+// { dg-do compile }
+
+template<typename T>
+struct remove_reference
+{
+  typedef T type;
+};
+
+template<typename TestType>
+struct forward_as_lref
+{
+};
+
+template<typename Seq, typename N>
+struct apply1
+{
+  typedef typename remove_reference<Seq>::type seq;
+  typedef forward_as_lref<typename seq::seq_type> type; //#0
+};
+
+template<typename Seq>
+struct apply
+{
+  typedef forward_as_lref<typename remove_reference<Seq>::type::seq_type> type; //#1
+};
+
+struct reverse_view
+{
+  typedef int seq_type;
+};
+
+int
+main()
+{
+  apply<reverse_view >::type a2;
+}

-- 
	Dodji

[-- Attachment #3: Type: text/plain, Size: 13 bytes --]



-- 
	Dodji

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Dodji Seketeli] Patch PR c++/45200
  2010-08-11 18:30 [Dodji Seketeli] Patch PR c++/45200 Dodji Seketeli
@ 2010-08-11 21:04 ` Jason Merrill
  2010-08-11 21:06   ` Andrew Pinski
  2010-08-12 13:20   ` Dodji Seketeli
  0 siblings, 2 replies; 38+ messages in thread
From: Jason Merrill @ 2010-08-11 21:04 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

The change is OK, but the testcase looks over-reduced; apply1 isn't 
actually used at all.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Dodji Seketeli] Patch PR c++/45200
  2010-08-11 21:04 ` Jason Merrill
@ 2010-08-11 21:06   ` Andrew Pinski
  2010-08-12 13:20   ` Dodji Seketeli
  1 sibling, 0 replies; 38+ messages in thread
From: Andrew Pinski @ 2010-08-11 21:06 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Dodji Seketeli, GCC Patches

On Wed, Aug 11, 2010 at 2:00 PM, Jason Merrill <jason@redhat.com> wrote:
> The change is OK, but the testcase looks over-reduced; apply1 isn't actually
> used at all.

Maybe I over reduced it but the ICE happened even if apply1 was used or not.

Thanks,
Andrew Pinski

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Dodji Seketeli] Patch PR c++/45200
  2010-08-11 21:04 ` Jason Merrill
  2010-08-11 21:06   ` Andrew Pinski
@ 2010-08-12 13:20   ` Dodji Seketeli
  2010-08-12 14:35     ` Jason Merrill
  1 sibling, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-08-12 13:20 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Jason Merrill <jason@redhat.com> writes:

> The change is OK, but the testcase looks over-reduced; apply1 isn't
> actually used at all.

It's true that apply1 is not used but it is useful to trigger the bug
because it has a different number of template parameters than struct
apply. E.g, removing apply1 or removing its last template parameter
makes the crash to vanish.

-- 
	Dodji

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Dodji Seketeli] Patch PR c++/45200
  2010-08-12 13:20   ` Dodji Seketeli
@ 2010-08-12 14:35     ` Jason Merrill
  2010-08-13 10:30       ` Dodji Seketeli
  2010-09-19 22:34       ` Require canonical type comparison for typedefs again. (was Patch PR c++/45200) Dodji Seketeli
  0 siblings, 2 replies; 38+ messages in thread
From: Jason Merrill @ 2010-08-12 14:35 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

On 08/12/2010 09:16 AM, Dodji Seketeli wrote:
> Jason Merrill<jason@redhat.com>  writes:
>
>> The change is OK, but the testcase looks over-reduced; apply1 isn't
>> actually used at all.
>
> It's true that apply1 is not used but it is useful to trigger the bug
> because it has a different number of template parameters than struct
> apply. E.g, removing apply1 or removing its last template parameter
> makes the crash to vanish.

OK, then.

I'd like to see about moving back to using TYPE_CANONICAL to compare 
these types; it seems to me that might work if we just use different 
TYPE_CANONICAL for template parameters from parameter lists of different 
lengths.  So TYPE_CANONICAL would be the same for template type 
parameter 1 of 3 in all templates, but different from template type 
parameter 1 of 2.

Does that make sense to you?

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Dodji Seketeli] Patch PR c++/45200
  2010-08-12 14:35     ` Jason Merrill
@ 2010-08-13 10:30       ` Dodji Seketeli
  2010-08-13 15:09         ` Jason Merrill
  2010-09-19 22:34       ` Require canonical type comparison for typedefs again. (was Patch PR c++/45200) Dodji Seketeli
  1 sibling, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-08-13 10:30 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Jason Merrill <jason@redhat.com> writes:

> OK, then.
>
> I'd like to see about moving back to using TYPE_CANONICAL to compare
> these types; it seems to me that might work if we just use different
> TYPE_CANONICAL for template parameters from parameter lists of
> different lengths.  So TYPE_CANONICAL would be the same for template
> type parameter 1 of 3 in all templates, but different from template
> type parameter 1 of 2.
>
> Does that make sense to you?

I think that can work, yes. As I understand it the main benefit would be
to do away with the complex incompatible_dependent_types_p function.

Though, as we don't know the size of the full list of template parms
when we are building a given TEMPLATE_TYPE_PARM node I think we cannot
set its TYPE_CANONICAL at that moment, unlike how it is done now in
process_template_parm today. Rather, we would probably need to not set
the TYPE_CANONICAL at that moment, and and fix it up later when we know
the size of the list of template parsm, e.g. in end_template_parm_list.

That would let TYPE_CANONICAL in an incorrect state until the list of
template parms is parsed. Can't that lead to trouble?

-- 
	Dodji

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Dodji Seketeli] Patch PR c++/45200
  2010-08-13 10:30       ` Dodji Seketeli
@ 2010-08-13 15:09         ` Jason Merrill
  0 siblings, 0 replies; 38+ messages in thread
From: Jason Merrill @ 2010-08-13 15:09 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

On 08/13/2010 06:08 AM, Dodji Seketeli wrote:
> That would let TYPE_CANONICAL in an incorrect state until the list of
> template parms is parsed. Can't that lead to trouble?

Yeah, when we're done with the list we'd want to rebuild anything 
elsewhere in the list that uses one of the parms, like the type of a 
non-type parameter.  Or try to determine how many parameters there are 
before parsing any of them.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Require canonical type comparison for typedefs again. (was Patch PR c++/45200)
  2010-08-12 14:35     ` Jason Merrill
  2010-08-13 10:30       ` Dodji Seketeli
@ 2010-09-19 22:34       ` Dodji Seketeli
  2010-09-19 22:47         ` Paolo Carlini
  1 sibling, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-09-19 22:34 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Hello,

Jason Merrill <jason@redhat.com> writes:

> I'd like to see about moving back to using TYPE_CANONICAL to compare
> these types; it seems to me that might work if we just use different
> TYPE_CANONICAL for template parameters from parameter lists of
> different lengths.  So TYPE_CANONICAL would be the same for template
> type parameter 1 of 3 in all templates, but different from template
> type parameter 1 of 2.

I looked into this and came up with the candidate patch below. The
approach I tried was to first parse the template parms and require
structural comparison for dependent types created during the
parsing. When the template parms parsing is done I compute and set the
canonical types for dependent types. This fixup is done by first
computing canonical types of template type parameters and then tsubsting
into non-type template parameters as well as default template parameters
arguments.

The test I have added comes from PR c++/45606 that is currently open and
appears to be fixed by this patch.

Tested on x86_64-unknown-linux-gnu against trunk.

commit 3bf8a9f04eef6bf0bba480bd888d3aed2327c9c0
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for typedefs
    
    gcc/cp/ChangeLog:
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Extend this
    	accessor to make it work on TEMPLATE_TEMPLATE_PARMs too.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (canonical_type_parameter): The canonical type of template
    	type params now takes in account the total number of
    	template parms of a given template.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(current_template_args): Fix this for template template parameters.
    	(fixup_template_parms_canonical_types): New function.
    	(end_template_parm_list): Use it; compute the proper canonical
    	types for dependent types created during template parms parsing
    	and fixup those types accordingly. Set TEMPLATE_TYPE_PARM_SIBLING
    	on TEMPLATE_TEMPLATE_PARMs too.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(lookup_template_class): Make sure to require structural equality
    	for dependent types created during template parms parsing.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(type_dependent_expression_p): Don't crash on NULL expressions.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore. For TEMPLATE_TEMPLATE_PARM and TEMPLATE_TYPE_PARM, take
    	the length of template parms list in account when doing structural
    	comparison.
    	(comp_template_parms_position): Re-indent.
    
    gcc/testsuite/ChangeLog:
    	* g++.dg/template/typedef36.C: New test.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c594d6a..1537786 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6673,7 +6673,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c78beb7..7216f1a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4321,10 +4321,12 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
+/* The list of template parms that a given template type parameter
+   belongs to.  */
 #define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
+  (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM,    \
+		TEMPLATE_TEMPLATE_PARM,	       \
+		BOUND_TEMPLATE_TEMPLATE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5005,7 +5007,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5341,7 +5343,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 63197705..1c6bbbe 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 41feb57..a044659 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9385344..b8c35b3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10997,6 +10997,15 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms. Note that dependent
+     types created during this parsing require structural comparison
+     rather than canonical type comparison. This is because we first
+     need to know the total number of template parms to be able to
+     compute canonical types of each dependent type. So after the
+     loop, when we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11015,11 +11024,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5a90bdc..636a13b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -93,10 +93,14 @@ static GTY ((param_is (spec_entry)))
 static GTY ((param_is (spec_entry)))
   htab_t type_specializations;
 
-/* Contains canonical template parameter types. The vector is indexed by
-   the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
-   TREE_LIST, whose TREE_VALUEs contain the canonical template
-   parameters of various types and levels.  */
+/* Contains canonical template parameter types. The vector is indexed
+   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
+   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
+   total size of the template parameter list a given template
+   parameter would belong too, and whose TREE_VALUEs contain the
+   canonical template parameters of various types and levels,
+   belonging to a set of template parameters which size is
+   TREE_PURPOSE.  */
 static GTY(()) VEC(tree,gc) *canonical_template_parms;
 
 #define UNIFY_ALLOW_NONE 0
@@ -190,6 +194,8 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree current_template_args (void);
+static void fixup_template_parms_canonical_types (void);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3369,12 +3375,24 @@ build_template_parm_index (int index,
 
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
-   if no such parameter existed.  */
+   if no such parameter existed. TOTAL_NUM_PARMS is the number of
+   template parameters carried by the considered template.
+
+   If TYPE is the template parameter at position P in a
+   template, this function won't return the same canonical type as for
+   a another TYPE that would be a template parameter at position Q,
+   with Q != P.
+
+   if TOTAL_NUM_PARMS is 0, the function returns NULL_TREE.  */
 static tree
-canonical_type_parameter (tree type)
+canonical_type_parameter (tree type, unsigned total_num_parms)
 {
   tree list;
   int idx = TEMPLATE_TYPE_IDX (type);
+
+  if (total_num_parms == 0)
+    return NULL_TREE;
+
   if (!canonical_template_parms)
     canonical_template_parms = VEC_alloc (tree, gc, idx+1);
 
@@ -3382,15 +3400,20 @@ canonical_type_parameter (tree type)
     VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
 
   list = VEC_index (tree, canonical_template_parms, idx);
-  while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
-    list = TREE_CHAIN (list);
+  while (list)
+    {
+      if (TREE_INT_CST_LOW (TREE_PURPOSE (list)) == total_num_parms
+	  && comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+	break;
+      list = TREE_CHAIN (list);
+    }
 
   if (list)
     return TREE_VALUE (list);
   else
     {
       VEC_replace(tree, canonical_template_parms, idx,
-		  tree_cons (NULL_TREE, type, 
+		  tree_cons (size_int (total_num_parms), type, 
 			     VEC_index (tree, canonical_template_parms, idx)));
       return type;
     }
@@ -3438,15 +3461,21 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter can
+   be set to 0. Setting it to zero would create a template type
+   parameter with no canonical type.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3556,8 +3585,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 				     processing_template_decl,
 				     decl, TREE_TYPE (parm));
       TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
-      TYPE_CANONICAL (t) = canonical_type_parameter (t);
-    }
+      TYPE_CANONICAL (t) =
+	canonical_type_parameter (t, num_template_parms);
+   }
   DECL_ARTIFICIAL (decl) = 1;
   SET_DECL_TEMPLATE_PARM_P (decl);
   pushdecl (decl);
@@ -3586,16 +3616,94 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
+      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
+	  || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
 	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
 	      current_template_parms;
     }
 
+  fixup_template_parms_canonical_types ();
+
   --processing_template_parmlist;
 
   return saved_parmlist;
 }
 
+/* Walk the current template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static void
+fixup_template_parms_canonical_types (void)
+{
+  tree parm;
+  tree full_template_args;
+  tree parameter_vec;
+  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);
+
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree main_type, variant;
+
+      parm = TREE_VALUE (TREE_VEC_ELT (parameter_vec, i));
+      if (TREE_CODE (parm) == TYPE_DECL
+	  || TREE_CODE (parm) == TEMPLATE_DECL)
+	{
+	  /* Compute the canonical type of type template
+	     parameters and their variants.  */
+	  main_type = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+	  TYPE_CANONICAL (main_type) =
+	    canonical_type_parameter (main_type, num_parms);
+	  for (variant = TYPE_NEXT_VARIANT (main_type);
+	       variant;
+	       variant = TYPE_NEXT_VARIANT (variant))
+	    TYPE_CANONICAL (variant) =
+	      canonical_type_parameter (variant, num_parms);
+	}
+    }
+
+  full_template_args = current_template_args ();
+
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree cur = TREE_VEC_ELT (parameter_vec, i);
+
+      if ((TREE_CODE (TREE_VALUE (cur)) == TYPE_DECL
+	   || TREE_CODE (TREE_VALUE (cur)) == TEMPLATE_DECL)
+	  && TREE_PURPOSE (cur))
+	{
+	  tree default_arg = TREE_PURPOSE (cur);
+
+	  if (TYPE_P (default_arg)
+	      && !dependent_type_p (default_arg))
+	    continue;
+
+	  ++cp_unevaluated_operand;
+	  TREE_PURPOSE (cur) =
+	    tsubst_expr (default_arg, full_template_args,
+			 tf_none, default_arg, false);
+	  --cp_unevaluated_operand;
+	}
+
+      if (TREE_CODE (TREE_VALUE (cur)) == PARM_DECL)
+	{
+	  tree non_type_parm = TREE_VALUE (cur);
+	  ++cp_unevaluated_operand;
+	  TREE_VALUE (cur) =
+	    tsubst_decl (non_type_parm,
+			 full_template_args,
+			 tf_none);
+	  --cp_unevaluated_operand;
+	}
+    }
+}
+
 /* end_template_decl is called after a template declaration is seen.  */
 
 void
@@ -3706,7 +3814,23 @@ current_template_args (void)
       else
 	args = a;
     }
-
+  
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.
+      */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -6681,16 +6805,22 @@ lookup_template_class (tree d1,
 	  if (context == current_function_decl)
 	    pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
 
-	  if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
+	  if (any_template_arguments_need_structural_equality_p (arglist))
+	    /* Some of the template arguments require structural
+	       equality testing, so this template class requires
+	       structural equality testing. Note that we check this
+	       condition first because for dependent types that are
+	       created /during/ the parsing of template parameter lists,
+	       we must not require canonical type equality because
+	       canonical types of dependent types are actually going
+	       to be properly computed right at /the end/ of the
+	       template parms parsing.  */
+	    SET_TYPE_STRUCTURAL_EQUALITY (t);
+	  else if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
 	    /* This instantiation is another name for the primary
 	       template type. Set the TYPE_CANONICAL field
 	       appropriately. */
 	    TYPE_CANONICAL (t) = template_type;
-	  else if (any_template_arguments_need_structural_equality_p (arglist))
-	    /* Some of the template arguments require structural
-	       equality testing, so this template class requires
-	       structural equality testing. */
-	    SET_TYPE_STRUCTURAL_EQUALITY (t);
 	}
 
       /* If we called start_enum or pushtag above, this information
@@ -10291,7 +10421,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		else if (TYPE_STRUCTURAL_EQUALITY_P (t))
 		  SET_TYPE_STRUCTURAL_EQUALITY (r);
 		else
-		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
+		  {
+		    unsigned num_parms =
+		      (TEMPLATE_TYPE_PARM_SIBLING_PARMS (t))
+		      ? TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+					 (TEMPLATE_TYPE_PARM_SIBLING_PARMS (t)))
+		      : 0;
+		    TYPE_CANONICAL (r) =
+		      canonical_type_parameter (r, num_parms);
+		  }
 
 		if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
 		  {
@@ -17786,7 +17924,8 @@ type_dependent_expression_p (tree expression)
   if (!processing_template_decl)
     return false;
 
-  if (expression == error_mark_node)
+  if (expression == error_mark_node
+      || expression == NULL_TREE)
     return false;
 
   /* An unresolved name is always dependent.  */
@@ -18406,7 +18545,7 @@ make_auto (void)
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
     (0, processing_template_decl + 1, processing_template_decl + 1,
      TYPE_NAME (au), NULL_TREE);
-  TYPE_CANONICAL (au) = canonical_type_parameter (au);
+  TYPE_CANONICAL (au) = canonical_type_parameter (au, 0);
   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 ea01d1f..580ebf3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1063,22 +1063,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index 0ac95d0..fd5f92b 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,114 +1143,13 @@ comp_template_parms_position (tree t1, tree t2)
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
-
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
-    return false;
-
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+      || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+      || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
+	  != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1295,12 +1194,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1345,6 +1238,21 @@ structural_comptypes (tree t1, tree t2, int strict)
 	  (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
 	   DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2))))
 	return false;
+
+      if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	  != (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
+	return false;
+
+      /* If T1 and T2 belong to template parm lists of different
+	 size, then can't be equal.  */
+      if (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE
+	  && TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2)) != NULL_TREE
+	  && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+			       (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1))))
+	      != TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+				  (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2))))))
+	return false;
+
       if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
 	break;
       /* Don't check inheritance.  */
@@ -1401,8 +1309,24 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      {
+	/* If T1 and T2 don't have the same relative position in their
+	   template parameters set, they can't be equal.  */
+	if (!comp_template_parms_position (t1, t2))
+	  return false;
+	/* If T1 and T2 belong to template parm lists of different
+	   size, then can't be equal either.  */
+	if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	    != (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
+	  return false;
+	if (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE
+	    && TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2)) != NULL_TREE
+	    && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+				 (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1))))
+		!= TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+				    (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2))))))
+	  return false;
+      }
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..f6155c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+#include <list>
+
+template<class T>
+class Test
+{
+protected:
+  typedef std::list<T> ListAlias;
+  ListAlias list;
+public:
+  typedef typename ListAlias::const_iterator const_iterator;
+  inline const_iterator begin() const;
+
+};
+
+template<class T>
+inline typename std::list<T>::const_iterator Test<T>::begin() const
+{
+  return list.begin();
+}
+


-- 
	Dodji

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again. (was Patch PR c++/45200)
  2010-09-19 22:34       ` Require canonical type comparison for typedefs again. (was Patch PR c++/45200) Dodji Seketeli
@ 2010-09-19 22:47         ` Paolo Carlini
  2010-09-20 10:28           ` Require canonical type comparison for typedefs again Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Paolo Carlini @ 2010-09-19 22:47 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Jason Merrill, GCC Patches

Hi Dodji,

Minor nit...
> + if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) !=
> NULL_TREE)
> +	  != (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
> +	return false;
> +
> +      /* If T1 and T2 belong to template parm lists of different
> +	 size, then can't be equal.  */
> +      if (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE
> +	  && TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2)) != NULL_TREE
> +	  && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
> +			       (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1))))
> +	      != TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
> +				  (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2))))))
> +	return false;
> +
>        if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
>  	break;
>        /* Don't check inheritance.  */
> @@ -1401,8 +1309,24 @@ structural_comptypes (tree t1, tree t2, int strict)
>        break;
>  
>      case TEMPLATE_TYPE_PARM:
> -      /* If incompatible_dependent_types_p called earlier didn't decide
> -         T1 and T2 were different, they might be equal.  */
> +      {
> +	/* If T1 and T2 don't have the same relative position in their
> +	   template parameters set, they can't be equal.  */
> +	if (!comp_template_parms_position (t1, t2))
> +	  return false;
> +	/* If T1 and T2 belong to template parm lists of different
> +	   size, then can't be equal either.  */
> +	if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
> +	    != (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
> +	  return false;
> +	if (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1)) != NULL_TREE
> +	    && TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2)) != NULL_TREE
> +	    && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
> +				 (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1))))
> +		!= TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
> +				    (TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2))))))
> +	  return false;
> +      }
>        break;
>   
overlong lines?

Thanks!
Paolo.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-19 22:47         ` Paolo Carlini
@ 2010-09-20 10:28           ` Dodji Seketeli
  2010-09-20 15:35             ` H.J. Lu
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-09-20 10:28 UTC (permalink / raw)
  To: Paolo Carlini; +Cc: Jason Merrill, GCC Patches

Paolo Carlini <paolo.carlini@oracle.com> writes:

> Minor nit...

[...]

> overlong lines?

Oops, correct.

I have addressed that in the patch below and added better comments in
the offending region. Thanks.

-- 
	Dodji

commit 4e22c88fea32105dbfca1095c457643a1eae56de
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for typedefs
    
    gcc/cp/ChangeLog:
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Extend this
    	accessor to make it work on TEMPLATE_TEMPLATE_PARMs too.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (canonical_type_parameter): The canonical type of template
    	type params now takes in account the total number of
    	template parms of a given template.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(current_template_args): Fix this for template template parameters.
    	(fixup_template_parms_canonical_types): New function.
    	(end_template_parm_list): Use it; compute the proper canonical
    	types for dependent types created during template parms parsing
    	and fixup those types accordingly. Set TEMPLATE_TYPE_PARM_SIBLING
    	on TEMPLATE_TEMPLATE_PARMs too.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(lookup_template_class): Make sure to require structural equality
    	for dependent types created during template parms parsing.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(type_dependent_expression_p): Don't crash on NULL expressions.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore. For TEMPLATE_TEMPLATE_PARM and TEMPLATE_TYPE_PARM, take
    	the length of template parms list in account when doing structural
    	comparison.
    	(comp_template_parms_position): Re-indent.
    
    gcc/testsuite/ChangeLog:
    	* g++.dg/template/typedef36.C: New test.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c594d6a..1537786 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6673,7 +6673,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c78beb7..7216f1a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4321,10 +4321,12 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
+/* The list of template parms that a given template type parameter
+   belongs to.  */
 #define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
+  (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM,    \
+		TEMPLATE_TEMPLATE_PARM,	       \
+		BOUND_TEMPLATE_TEMPLATE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5005,7 +5007,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5341,7 +5343,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 63197705..1c6bbbe 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 41feb57..a044659 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9385344..b8c35b3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10997,6 +10997,15 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms. Note that dependent
+     types created during this parsing require structural comparison
+     rather than canonical type comparison. This is because we first
+     need to know the total number of template parms to be able to
+     compute canonical types of each dependent type. So after the
+     loop, when we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11015,11 +11024,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5a90bdc..636a13b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -93,10 +93,14 @@ static GTY ((param_is (spec_entry)))
 static GTY ((param_is (spec_entry)))
   htab_t type_specializations;
 
-/* Contains canonical template parameter types. The vector is indexed by
-   the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
-   TREE_LIST, whose TREE_VALUEs contain the canonical template
-   parameters of various types and levels.  */
+/* Contains canonical template parameter types. The vector is indexed
+   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
+   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
+   total size of the template parameter list a given template
+   parameter would belong too, and whose TREE_VALUEs contain the
+   canonical template parameters of various types and levels,
+   belonging to a set of template parameters which size is
+   TREE_PURPOSE.  */
 static GTY(()) VEC(tree,gc) *canonical_template_parms;
 
 #define UNIFY_ALLOW_NONE 0
@@ -190,6 +194,8 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree current_template_args (void);
+static void fixup_template_parms_canonical_types (void);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3369,12 +3375,24 @@ build_template_parm_index (int index,
 
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
-   if no such parameter existed.  */
+   if no such parameter existed. TOTAL_NUM_PARMS is the number of
+   template parameters carried by the considered template.
+
+   If TYPE is the template parameter at position P in a
+   template, this function won't return the same canonical type as for
+   a another TYPE that would be a template parameter at position Q,
+   with Q != P.
+
+   if TOTAL_NUM_PARMS is 0, the function returns NULL_TREE.  */
 static tree
-canonical_type_parameter (tree type)
+canonical_type_parameter (tree type, unsigned total_num_parms)
 {
   tree list;
   int idx = TEMPLATE_TYPE_IDX (type);
+
+  if (total_num_parms == 0)
+    return NULL_TREE;
+
   if (!canonical_template_parms)
     canonical_template_parms = VEC_alloc (tree, gc, idx+1);
 
@@ -3382,15 +3400,20 @@ canonical_type_parameter (tree type)
     VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
 
   list = VEC_index (tree, canonical_template_parms, idx);
-  while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
-    list = TREE_CHAIN (list);
+  while (list)
+    {
+      if (TREE_INT_CST_LOW (TREE_PURPOSE (list)) == total_num_parms
+	  && comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+	break;
+      list = TREE_CHAIN (list);
+    }
 
   if (list)
     return TREE_VALUE (list);
   else
     {
       VEC_replace(tree, canonical_template_parms, idx,
-		  tree_cons (NULL_TREE, type, 
+		  tree_cons (size_int (total_num_parms), type, 
 			     VEC_index (tree, canonical_template_parms, idx)));
       return type;
     }
@@ -3438,15 +3461,21 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter can
+   be set to 0. Setting it to zero would create a template type
+   parameter with no canonical type.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3556,8 +3585,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 				     processing_template_decl,
 				     decl, TREE_TYPE (parm));
       TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
-      TYPE_CANONICAL (t) = canonical_type_parameter (t);
-    }
+      TYPE_CANONICAL (t) =
+	canonical_type_parameter (t, num_template_parms);
+   }
   DECL_ARTIFICIAL (decl) = 1;
   SET_DECL_TEMPLATE_PARM_P (decl);
   pushdecl (decl);
@@ -3586,16 +3616,94 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
+      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
+	  || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
 	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
 	      current_template_parms;
     }
 
+  fixup_template_parms_canonical_types ();
+
   --processing_template_parmlist;
 
   return saved_parmlist;
 }
 
+/* Walk current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static void
+fixup_template_parms_canonical_types (void)
+{
+  tree parm;
+  tree full_template_args;
+  tree parameter_vec;
+  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);
+
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree main_type, variant;
+
+      parm = TREE_VALUE (TREE_VEC_ELT (parameter_vec, i));
+      if (TREE_CODE (parm) == TYPE_DECL
+	  || TREE_CODE (parm) == TEMPLATE_DECL)
+	{
+	  /* Compute the canonical type of type template
+	     parameters and their variants.  */
+	  main_type = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+	  TYPE_CANONICAL (main_type) =
+	    canonical_type_parameter (main_type, num_parms);
+	  for (variant = TYPE_NEXT_VARIANT (main_type);
+	       variant;
+	       variant = TYPE_NEXT_VARIANT (variant))
+	    TYPE_CANONICAL (variant) =
+	      canonical_type_parameter (variant, num_parms);
+	}
+    }
+
+  full_template_args = current_template_args ();
+
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree cur = TREE_VEC_ELT (parameter_vec, i);
+
+      if ((TREE_CODE (TREE_VALUE (cur)) == TYPE_DECL
+	   || TREE_CODE (TREE_VALUE (cur)) == TEMPLATE_DECL)
+	  && TREE_PURPOSE (cur))
+	{
+	  tree default_arg = TREE_PURPOSE (cur);
+
+	  if (TYPE_P (default_arg)
+	      && !dependent_type_p (default_arg))
+	    continue;
+
+	  ++cp_unevaluated_operand;
+	  TREE_PURPOSE (cur) =
+	    tsubst_expr (default_arg, full_template_args,
+			 tf_none, default_arg, false);
+	  --cp_unevaluated_operand;
+	}
+
+      if (TREE_CODE (TREE_VALUE (cur)) == PARM_DECL)
+	{
+	  tree non_type_parm = TREE_VALUE (cur);
+	  ++cp_unevaluated_operand;
+	  TREE_VALUE (cur) =
+	    tsubst_decl (non_type_parm,
+			 full_template_args,
+			 tf_none);
+	  --cp_unevaluated_operand;
+	}
+    }
+}
+
 /* end_template_decl is called after a template declaration is seen.  */
 
 void
@@ -3706,7 +3814,23 @@ current_template_args (void)
       else
 	args = a;
     }
-
+  
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.
+      */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -6681,16 +6805,22 @@ lookup_template_class (tree d1,
 	  if (context == current_function_decl)
 	    pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
 
-	  if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
+	  if (any_template_arguments_need_structural_equality_p (arglist))
+	    /* Some of the template arguments require structural
+	       equality testing, so this template class requires
+	       structural equality testing. Note that we check this
+	       condition first because for dependent types that are
+	       created /during/ the parsing of template parameter lists,
+	       we must not require canonical type equality because
+	       canonical types of dependent types are actually going
+	       to be properly computed right at /the end/ of the
+	       template parms parsing.  */
+	    SET_TYPE_STRUCTURAL_EQUALITY (t);
+	  else if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
 	    /* This instantiation is another name for the primary
 	       template type. Set the TYPE_CANONICAL field
 	       appropriately. */
 	    TYPE_CANONICAL (t) = template_type;
-	  else if (any_template_arguments_need_structural_equality_p (arglist))
-	    /* Some of the template arguments require structural
-	       equality testing, so this template class requires
-	       structural equality testing. */
-	    SET_TYPE_STRUCTURAL_EQUALITY (t);
 	}
 
       /* If we called start_enum or pushtag above, this information
@@ -10291,7 +10421,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		else if (TYPE_STRUCTURAL_EQUALITY_P (t))
 		  SET_TYPE_STRUCTURAL_EQUALITY (r);
 		else
-		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
+		  {
+		    unsigned num_parms =
+		      (TEMPLATE_TYPE_PARM_SIBLING_PARMS (t))
+		      ? TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+					 (TEMPLATE_TYPE_PARM_SIBLING_PARMS (t)))
+		      : 0;
+		    TYPE_CANONICAL (r) =
+		      canonical_type_parameter (r, num_parms);
+		  }
 
 		if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
 		  {
@@ -17786,7 +17924,8 @@ type_dependent_expression_p (tree expression)
   if (!processing_template_decl)
     return false;
 
-  if (expression == error_mark_node)
+  if (expression == error_mark_node
+      || expression == NULL_TREE)
     return false;
 
   /* An unresolved name is always dependent.  */
@@ -18406,7 +18545,7 @@ make_auto (void)
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
     (0, processing_template_decl + 1, processing_template_decl + 1,
      TYPE_NAME (au), NULL_TREE);
-  TYPE_CANONICAL (au) = canonical_type_parameter (au);
+  TYPE_CANONICAL (au) = canonical_type_parameter (au, 0);
   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 ea01d1f..580ebf3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1063,22 +1063,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index 0ac95d0..6524b3c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,114 +1143,13 @@ comp_template_parms_position (tree t1, tree t2)
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
+  if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+      || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+      || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
+	  != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
     return false;
 
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
-
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
-    return false;
-
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
-    return false;
-
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1295,12 +1194,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1345,6 +1238,30 @@ structural_comptypes (tree t1, tree t2, int strict)
 	  (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
 	   DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2))))
 	return false;
+
+      /* If T1 belongs to a not-yet fully parsed template parameters
+	 list, let's assume it's different from T2 which belongs to an
+	 already fully parsed template template parameters list.  */
+      if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	   (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	  != (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	      (TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
+	return false;
+
+      /* If T1 and T2 belong to template parm lists of different
+	 size, then can't be equal.  */
+      if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	   (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	  && (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	      (TYPE_MAIN_VARIANT (t2)) != NULL_TREE)
+	  && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+			       (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+				(TYPE_MAIN_VARIANT (t1))))
+	      != TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+				  (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+				   (TYPE_MAIN_VARIANT (t2))))))
+	return false;
+
       if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
 	break;
       /* Don't check inheritance.  */
@@ -1401,8 +1318,35 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      {
+	/* If T1 and T2 don't have the same relative position in their
+	   template parameters set, they can't be equal.  */
+	if (!comp_template_parms_position (t1, t2))
+	  return false;
+
+	/* If T1 belongs to a not-yet fully parsed template parameters
+	 list, let's assume it's different from T2 which belongs to an
+	 already fully parsed template template parameters list.  */
+	if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	     (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	    != (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+		(TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
+	  return false;
+	
+	/* If T1 and T2 belong to template parm lists of different
+	   size, then can't be equal either.  */
+	if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	     (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	    && (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+		(TYPE_MAIN_VARIANT (t2)) != NULL_TREE)
+	    && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+				 (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+				  (TYPE_MAIN_VARIANT (t1))))
+		!= TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+				    (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+				     (TYPE_MAIN_VARIANT (t2))))))
+	  return false;
+      }
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..f6155c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+#include <list>
+
+template<class T>
+class Test
+{
+protected:
+  typedef std::list<T> ListAlias;
+  ListAlias list;
+public:
+  typedef typename ListAlias::const_iterator const_iterator;
+  inline const_iterator begin() const;
+
+};
+
+template<class T>
+inline typename std::list<T>::const_iterator Test<T>::begin() const
+{
+  return list.begin();
+}
+

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-20 10:28           ` Require canonical type comparison for typedefs again Dodji Seketeli
@ 2010-09-20 15:35             ` H.J. Lu
  2010-09-20 17:07               ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: H.J. Lu @ 2010-09-20 15:35 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, Jason Merrill, GCC Patches

On Mon, Sep 20, 2010 at 3:07 AM, Dodji Seketeli <dodji@redhat.com> wrote:
> Paolo Carlini <paolo.carlini@oracle.com> writes:
>
>> Minor nit...
>
> [...]
>
>> overlong lines?
>
> Oops, correct.
>
> I have addressed that in the patch below and added better comments in
> the offending region. Thanks.
>
> --
>        Dodji
>
> commit 4e22c88fea32105dbfca1095c457643a1eae56de
> Author: Dodji Seketeli <dodji@redhat.com>
> Date:   Mon Sep 13 12:12:21 2010 +0200
>
>    Restore canonical type comparison for typedefs
>
>    gcc/cp/ChangeLog:
>        * cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Extend this
>        accessor to make it work on TEMPLATE_TEMPLATE_PARMs too.

Does this patch fix a bug? If yes, please include PR # in ChangeLog entries.

Thanks.



-- 
H.J.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-20 15:35             ` H.J. Lu
@ 2010-09-20 17:07               ` Dodji Seketeli
  2010-09-20 21:44                 ` Jason Merrill
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-09-20 17:07 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Paolo Carlini, Jason Merrill, GCC Patches

"H.J. Lu" <hjl.tools@gmail.com> writes:

> Does this patch fix a bug? If yes, please include PR # in ChangeLog
> entries.

Yes it does fix PR c++/45606. Here is a patch with ChangeLog updated
accordingly.

Thanks.

-- 
	Dodji

commit 7ab3f3b0fd3885eeab862bc2f4b44af1c4115512
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Extend this
    	accessor to make it work on TEMPLATE_TEMPLATE_PARMs too.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (canonical_type_parameter): The canonical type of template
    	type params now takes in account the total number of
    	template parms of a given template.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(current_template_args): Fix this for template template parameters.
    	(fixup_template_parms_canonical_types): New function.
    	(end_template_parm_list): Use it; compute the proper canonical
    	types for dependent types created during template parms parsing
    	and fixup those types accordingly. Set TEMPLATE_TYPE_PARM_SIBLING
    	on TEMPLATE_TEMPLATE_PARMs too.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(lookup_template_class): Make sure to require structural equality
    	for dependent types created during template parms parsing.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(type_dependent_expression_p): Don't crash on NULL expressions.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore. For TEMPLATE_TEMPLATE_PARM and TEMPLATE_TYPE_PARM, take
    	the length of template parms list in account when doing structural
    	comparison.
    	(comp_template_parms_position): Re-indent.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* g++.dg/template/typedef36.C: New test.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c594d6a..1537786 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6673,7 +6673,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c78beb7..7216f1a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4321,10 +4321,12 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
+/* The list of template parms that a given template type parameter
+   belongs to.  */
 #define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
+  (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM,    \
+		TEMPLATE_TEMPLATE_PARM,	       \
+		BOUND_TEMPLATE_TEMPLATE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5005,7 +5007,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5341,7 +5343,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 63197705..1c6bbbe 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 41feb57..a044659 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9385344..b8c35b3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10997,6 +10997,15 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms. Note that dependent
+     types created during this parsing require structural comparison
+     rather than canonical type comparison. This is because we first
+     need to know the total number of template parms to be able to
+     compute canonical types of each dependent type. So after the
+     loop, when we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11015,11 +11024,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5a90bdc..636a13b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -93,10 +93,14 @@ static GTY ((param_is (spec_entry)))
 static GTY ((param_is (spec_entry)))
   htab_t type_specializations;
 
-/* Contains canonical template parameter types. The vector is indexed by
-   the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
-   TREE_LIST, whose TREE_VALUEs contain the canonical template
-   parameters of various types and levels.  */
+/* Contains canonical template parameter types. The vector is indexed
+   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
+   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
+   total size of the template parameter list a given template
+   parameter would belong too, and whose TREE_VALUEs contain the
+   canonical template parameters of various types and levels,
+   belonging to a set of template parameters which size is
+   TREE_PURPOSE.  */
 static GTY(()) VEC(tree,gc) *canonical_template_parms;
 
 #define UNIFY_ALLOW_NONE 0
@@ -190,6 +194,8 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree current_template_args (void);
+static void fixup_template_parms_canonical_types (void);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3369,12 +3375,24 @@ build_template_parm_index (int index,
 
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
-   if no such parameter existed.  */
+   if no such parameter existed. TOTAL_NUM_PARMS is the number of
+   template parameters carried by the considered template.
+
+   If TYPE is the template parameter at position P in a
+   template, this function won't return the same canonical type as for
+   a another TYPE that would be a template parameter at position Q,
+   with Q != P.
+
+   if TOTAL_NUM_PARMS is 0, the function returns NULL_TREE.  */
 static tree
-canonical_type_parameter (tree type)
+canonical_type_parameter (tree type, unsigned total_num_parms)
 {
   tree list;
   int idx = TEMPLATE_TYPE_IDX (type);
+
+  if (total_num_parms == 0)
+    return NULL_TREE;
+
   if (!canonical_template_parms)
     canonical_template_parms = VEC_alloc (tree, gc, idx+1);
 
@@ -3382,15 +3400,20 @@ canonical_type_parameter (tree type)
     VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
 
   list = VEC_index (tree, canonical_template_parms, idx);
-  while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
-    list = TREE_CHAIN (list);
+  while (list)
+    {
+      if (TREE_INT_CST_LOW (TREE_PURPOSE (list)) == total_num_parms
+	  && comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+	break;
+      list = TREE_CHAIN (list);
+    }
 
   if (list)
     return TREE_VALUE (list);
   else
     {
       VEC_replace(tree, canonical_template_parms, idx,
-		  tree_cons (NULL_TREE, type, 
+		  tree_cons (size_int (total_num_parms), type, 
 			     VEC_index (tree, canonical_template_parms, idx)));
       return type;
     }
@@ -3438,15 +3461,21 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter can
+   be set to 0. Setting it to zero would create a template type
+   parameter with no canonical type.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3556,8 +3585,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 				     processing_template_decl,
 				     decl, TREE_TYPE (parm));
       TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
-      TYPE_CANONICAL (t) = canonical_type_parameter (t);
-    }
+      TYPE_CANONICAL (t) =
+	canonical_type_parameter (t, num_template_parms);
+   }
   DECL_ARTIFICIAL (decl) = 1;
   SET_DECL_TEMPLATE_PARM_P (decl);
   pushdecl (decl);
@@ -3586,16 +3616,94 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
+      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
+	  || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
 	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
 	      current_template_parms;
     }
 
+  fixup_template_parms_canonical_types ();
+
   --processing_template_parmlist;
 
   return saved_parmlist;
 }
 
+/* Walk current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static void
+fixup_template_parms_canonical_types (void)
+{
+  tree parm;
+  tree full_template_args;
+  tree parameter_vec;
+  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);
+
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree main_type, variant;
+
+      parm = TREE_VALUE (TREE_VEC_ELT (parameter_vec, i));
+      if (TREE_CODE (parm) == TYPE_DECL
+	  || TREE_CODE (parm) == TEMPLATE_DECL)
+	{
+	  /* Compute the canonical type of type template
+	     parameters and their variants.  */
+	  main_type = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+	  TYPE_CANONICAL (main_type) =
+	    canonical_type_parameter (main_type, num_parms);
+	  for (variant = TYPE_NEXT_VARIANT (main_type);
+	       variant;
+	       variant = TYPE_NEXT_VARIANT (variant))
+	    TYPE_CANONICAL (variant) =
+	      canonical_type_parameter (variant, num_parms);
+	}
+    }
+
+  full_template_args = current_template_args ();
+
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree cur = TREE_VEC_ELT (parameter_vec, i);
+
+      if ((TREE_CODE (TREE_VALUE (cur)) == TYPE_DECL
+	   || TREE_CODE (TREE_VALUE (cur)) == TEMPLATE_DECL)
+	  && TREE_PURPOSE (cur))
+	{
+	  tree default_arg = TREE_PURPOSE (cur);
+
+	  if (TYPE_P (default_arg)
+	      && !dependent_type_p (default_arg))
+	    continue;
+
+	  ++cp_unevaluated_operand;
+	  TREE_PURPOSE (cur) =
+	    tsubst_expr (default_arg, full_template_args,
+			 tf_none, default_arg, false);
+	  --cp_unevaluated_operand;
+	}
+
+      if (TREE_CODE (TREE_VALUE (cur)) == PARM_DECL)
+	{
+	  tree non_type_parm = TREE_VALUE (cur);
+	  ++cp_unevaluated_operand;
+	  TREE_VALUE (cur) =
+	    tsubst_decl (non_type_parm,
+			 full_template_args,
+			 tf_none);
+	  --cp_unevaluated_operand;
+	}
+    }
+}
+
 /* end_template_decl is called after a template declaration is seen.  */
 
 void
@@ -3706,7 +3814,23 @@ current_template_args (void)
       else
 	args = a;
     }
-
+  
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.
+      */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -6681,16 +6805,22 @@ lookup_template_class (tree d1,
 	  if (context == current_function_decl)
 	    pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
 
-	  if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
+	  if (any_template_arguments_need_structural_equality_p (arglist))
+	    /* Some of the template arguments require structural
+	       equality testing, so this template class requires
+	       structural equality testing. Note that we check this
+	       condition first because for dependent types that are
+	       created /during/ the parsing of template parameter lists,
+	       we must not require canonical type equality because
+	       canonical types of dependent types are actually going
+	       to be properly computed right at /the end/ of the
+	       template parms parsing.  */
+	    SET_TYPE_STRUCTURAL_EQUALITY (t);
+	  else if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
 	    /* This instantiation is another name for the primary
 	       template type. Set the TYPE_CANONICAL field
 	       appropriately. */
 	    TYPE_CANONICAL (t) = template_type;
-	  else if (any_template_arguments_need_structural_equality_p (arglist))
-	    /* Some of the template arguments require structural
-	       equality testing, so this template class requires
-	       structural equality testing. */
-	    SET_TYPE_STRUCTURAL_EQUALITY (t);
 	}
 
       /* If we called start_enum or pushtag above, this information
@@ -10291,7 +10421,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		else if (TYPE_STRUCTURAL_EQUALITY_P (t))
 		  SET_TYPE_STRUCTURAL_EQUALITY (r);
 		else
-		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
+		  {
+		    unsigned num_parms =
+		      (TEMPLATE_TYPE_PARM_SIBLING_PARMS (t))
+		      ? TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+					 (TEMPLATE_TYPE_PARM_SIBLING_PARMS (t)))
+		      : 0;
+		    TYPE_CANONICAL (r) =
+		      canonical_type_parameter (r, num_parms);
+		  }
 
 		if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
 		  {
@@ -17786,7 +17924,8 @@ type_dependent_expression_p (tree expression)
   if (!processing_template_decl)
     return false;
 
-  if (expression == error_mark_node)
+  if (expression == error_mark_node
+      || expression == NULL_TREE)
     return false;
 
   /* An unresolved name is always dependent.  */
@@ -18406,7 +18545,7 @@ make_auto (void)
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
     (0, processing_template_decl + 1, processing_template_decl + 1,
      TYPE_NAME (au), NULL_TREE);
-  TYPE_CANONICAL (au) = canonical_type_parameter (au);
+  TYPE_CANONICAL (au) = canonical_type_parameter (au, 0);
   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 ea01d1f..580ebf3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1063,22 +1063,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index 0ac95d0..6524b3c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,114 +1143,13 @@ comp_template_parms_position (tree t1, tree t2)
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
+  if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+      || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+      || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
+	  != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
     return false;
 
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
-
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
-    return false;
-
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
-    return false;
-
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1295,12 +1194,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1345,6 +1238,30 @@ structural_comptypes (tree t1, tree t2, int strict)
 	  (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
 	   DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2))))
 	return false;
+
+      /* If T1 belongs to a not-yet fully parsed template parameters
+	 list, let's assume it's different from T2 which belongs to an
+	 already fully parsed template template parameters list.  */
+      if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	   (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	  != (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	      (TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
+	return false;
+
+      /* If T1 and T2 belong to template parm lists of different
+	 size, then can't be equal.  */
+      if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	   (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	  && (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	      (TYPE_MAIN_VARIANT (t2)) != NULL_TREE)
+	  && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+			       (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+				(TYPE_MAIN_VARIANT (t1))))
+	      != TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+				  (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+				   (TYPE_MAIN_VARIANT (t2))))))
+	return false;
+
       if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
 	break;
       /* Don't check inheritance.  */
@@ -1401,8 +1318,35 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      {
+	/* If T1 and T2 don't have the same relative position in their
+	   template parameters set, they can't be equal.  */
+	if (!comp_template_parms_position (t1, t2))
+	  return false;
+
+	/* If T1 belongs to a not-yet fully parsed template parameters
+	 list, let's assume it's different from T2 which belongs to an
+	 already fully parsed template template parameters list.  */
+	if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	     (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	    != (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+		(TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
+	  return false;
+	
+	/* If T1 and T2 belong to template parm lists of different
+	   size, then can't be equal either.  */
+	if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
+	     (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
+	    && (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+		(TYPE_MAIN_VARIANT (t2)) != NULL_TREE)
+	    && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+				 (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+				  (TYPE_MAIN_VARIANT (t1))))
+		!= TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+				    (TEMPLATE_TYPE_PARM_SIBLING_PARMS
+				     (TYPE_MAIN_VARIANT (t2))))))
+	  return false;
+      }
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..f6155c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+#include <list>
+
+template<class T>
+class Test
+{
+protected:
+  typedef std::list<T> ListAlias;
+  ListAlias list;
+public:
+  typedef typename ListAlias::const_iterator const_iterator;
+  inline const_iterator begin() const;
+
+};
+
+template<class T>
+inline typename std::list<T>::const_iterator Test<T>::begin() const
+{
+  return list.begin();
+}
+

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-20 17:07               ` Dodji Seketeli
@ 2010-09-20 21:44                 ` Jason Merrill
  2010-09-26 14:44                   ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Jason Merrill @ 2010-09-20 21:44 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

On 09/20/2010 12:29 PM, Dodji Seketeli wrote:
>  #define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
> -  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
> +  (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM,    \
> +		TEMPLATE_TEMPLATE_PARM,	       \
> +		BOUND_TEMPLATE_TEMPLATE_PARM))->type.maxval

With your patch we aren't actually using this list anymore, only its 
length, so we might as well just store the length directly rather than 
the list.  That way, this:

> +      /* If T1 belongs to a not-yet fully parsed template parameters
> +	 list, let's assume it's different from T2 which belongs to an
> +	 already fully parsed template template parameters list.  */
> +      if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
> +	   (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
> +	  != (TEMPLATE_TYPE_PARM_SIBLING_PARMS
> +	      (TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
> +	return false;
> +
> +      /* If T1 and T2 belong to template parm lists of different
> +	 size, then can't be equal.  */
> +      if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
> +	   (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
> +	  && (TEMPLATE_TYPE_PARM_SIBLING_PARMS
> +	      (TYPE_MAIN_VARIANT (t2)) != NULL_TREE)
> +	  && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
> +			       (TEMPLATE_TYPE_PARM_SIBLING_PARMS
> +				(TYPE_MAIN_VARIANT (t1))))
> +	      != TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
> +				  (TEMPLATE_TYPE_PARM_SIBLING_PARMS
> +				   (TYPE_MAIN_VARIANT (t2))))))
> +	return false;

Can become a single simple comparison.  Which should go into 
comp_template_parms_position.

> +/* Contains canonical template parameter types. The vector is indexed
> +   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
> +   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
> +   total size of the template parameter list a given template
> +   parameter would belong too, and whose TREE_VALUEs contain the
> +   canonical template parameters of various types and levels,
> +   belonging to a set of template parameters which size is
> +   TREE_PURPOSE.  */
>  static GTY(()) VEC(tree,gc) *canonical_template_parms;

Since we're adding more elements to this table, maybe we should convert 
it to a hash table.  But that can be a follow-on patch.

> +  if (total_num_parms == 0)
> +    return NULL_TREE;

Since you're already treating parms from a list of unknown length as 
distinct from parms from a list of known length, we can give them a 
canonical type, too.

> +      if (TREE_CODE (parm) == TYPE_DECL
> +	     || TREE_CODE (parm) == TEMPLATE_DECL)
> +	{
> +	  /* Compute the canonical type of type template
> +	     parameters and their variants.  */

Hmm, don't we need to handle substituting type parameters into template 
parameters?

template <class T, template <T> class U> struct A { };

It should work to do a single loop over the template args, doing any 
substitution and then replacing them with their canonical variants as 
appropriate.  Since a particular parameter can only refer to previous 
ones, we can't run into ordering issues.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-20 21:44                 ` Jason Merrill
@ 2010-09-26 14:44                   ` Dodji Seketeli
  2010-09-26 15:10                     ` Jason Merrill
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-09-26 14:44 UTC (permalink / raw)
  To: Jason Merrill; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

Hello,

I have reworked the patch to address your points. Please see my comments
below.

Jason Merrill <jason@redhat.com> writes:

> On 09/20/2010 12:29 PM, Dodji Seketeli wrote:
>>  #define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
>> -  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
>> +  (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM,    \
>> +		TEMPLATE_TEMPLATE_PARM,	       \
>> +		BOUND_TEMPLATE_TEMPLATE_PARM))->type.maxval
>
> With your patch we aren't actually using this list anymore, only its
> length, so we might as well just store the length directly rather than
> the list.  That way, this:
>
>> +      /* If T1 belongs to a not-yet fully parsed template parameters
>> +	 list, let's assume it's different from T2 which belongs to an
>> +	 already fully parsed template template parameters list.  */
>> +      if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
>> +	   (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
>> +	  != (TEMPLATE_TYPE_PARM_SIBLING_PARMS
>> +	      (TYPE_MAIN_VARIANT (t1)) != NULL_TREE))
>> +	return false;
>> +
>> +      /* If T1 and T2 belong to template parm lists of different
>> +	 size, then can't be equal.  */
>> +      if ((TEMPLATE_TYPE_PARM_SIBLING_PARMS
>> +	   (TYPE_MAIN_VARIANT (t1)) != NULL_TREE)
>> +	  && (TEMPLATE_TYPE_PARM_SIBLING_PARMS
>> +	      (TYPE_MAIN_VARIANT (t2)) != NULL_TREE)
>> +	  && (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
>> +			       (TEMPLATE_TYPE_PARM_SIBLING_PARMS
>> +				(TYPE_MAIN_VARIANT (t1))))
>> +	      != TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
>> +				  (TEMPLATE_TYPE_PARM_SIBLING_PARMS
>> +				   (TYPE_MAIN_VARIANT (t2))))))
>> +	return false;
>
> Can become a single simple comparison.  Which should go into
> comp_template_parms_position.
>

Nice. I have done that.

>> +/* Contains canonical template parameter types. The vector is indexed
>> +   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
>> +   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
>> +   total size of the template parameter list a given template
>> +   parameter would belong too, and whose TREE_VALUEs contain the
>> +   canonical template parameters of various types and levels,
>> +   belonging to a set of template parameters which size is
>> +   TREE_PURPOSE.  */
>>  static GTY(()) VEC(tree,gc) *canonical_template_parms;
>
> Since we're adding more elements to this table, maybe we should
> convert it to a hash table.  But that can be a follow-on patch.
>

Sure. I'll post a separate patch for it once we are done with this one.

>> +  if (total_num_parms == 0)
>> +    return NULL_TREE;
>
> Since you're already treating parms from a list of unknown length as
> distinct from parms from a list of known length, we can give them a
> canonical type, too.
>

Doing that doesn't seem to work. The problem is not with the comparison
of type template parms but rather with the comparison of dependent types
created during the template parms parsing.

If type template parms don't require structural comparison then a type A
(created during template parms parsing) dependent on those parms will
have a canonical type. The fixup then creates a type A' that is
structurally equivalent to A, but has a different canonical type. Later,
possible calls to lookup_template_class could then compare A and A' and
the sanity constraints activated by ENABLE_CHECKING in comptypes would
be violated because two structurally equivalent types have different
canonical types.

We don't have the issue in comptypes if A doesn't have a canonical type
to begin with.

>> +      if (TREE_CODE (parm) == TYPE_DECL
>> +	     || TREE_CODE (parm) == TEMPLATE_DECL)
>> +	{
>> +	  /* Compute the canonical type of type template
>> +	     parameters and their variants.  */
>
> Hmm, don't we need to handle substituting type parameters into
> template parameters?
>
> template <class T, template <T> class U> struct A { };
>
> It should work to do a single loop over the template args, doing any
> substitution and then replacing them with their canonical variants as
> appropriate.  Since a particular parameter can only refer to previous
> ones, we can't run into ordering issues.
>

Good catch.

I have done this but it made me scratch head for a little while because
tsubsting into the parms of a template template parm wasn't as straight
forward as I thought it would be.

The issue where the followings.

* Template parm level reduction.

When at least one of the parms is itself a template [like in
testsuite/g++.old-deja/g++.pt/nttp1.C] then at some point we end up in
tsubst (at least) with an argument set that has a depth that is less
than the depth of the parm of the template template parm we are
susbtituting into.

My understanding is that the tsubsting code then thinks that we are
doing the substitution for the purpose of instantiation and then reduces
the level of the resulting parms.

In this current case though, we are not doing the substitution for the
purpose of instantiation; we want the levels of all the resulting
tsubsted parms to remain unchanged; we want an "in place substitution"
so to speak.

So I introduced a new tf_no_tpl_reduce (for "no template parm level
reduce") flag in enum tsubst_flags and changed tsubst and
tsubst_template_parms to avoid doing level reduction when passed this
flag.]

Incidentally I noticed that the tf_no_class_instantiation is not used by
any client code anymore. Would you accept a patchlet to remove it?

* I had to use use_template_parms in make_typename_type

I know I have to be careful each time I use use_template_parms instead
of dependent_type_p so I'll give some context.

Consider this example distilled from testsuite/g++.dg/template/ttp25.C:

~=~
template<typename T> struct metafun { typedef T type; };

template<typename T, template<typename metafun<T>::type> class C> //#0
void f4(T, C<5>);

template<int N> struct X {};
void g() {
  f4(5, X<5>()); // OK.
}
~=~

Consider when we build the set of overload candidate functions for
f4(5, X<5>()). add_template_candidate_real at some point tries to deduce the
template argument to C.

During unification of C<5> with X<5> the argument 5 of X is converted
into the type of the parameter of C, i.e 5 is converted into typename
metafun<T>::type. convert_template_argument then tries to substitute
into typename metafun<T>::type. This should just create another
equivalent typename becase metafun<T> is dependent and thus non
complete. But when tsubst calls make_typename_type, the later fails to
detect that metafun<T> is dependent [because processing_template_decl is
0] and goes crazy. As tsubst uses use_template_parms to detect that
metafun<T> is dependent before calling make_typename_type, I thought I'd
use the same in the later.

Interestingly, the reason why this wasn't happening before is, in #0,
when lookup_class_template is called to build the type of metafun<T>,
that template-id is considered as naming template<class T> struct
metafun; so its canonical type is set to the TREE_TYPE of the
TEMPLATE_DECL of metafun. That type is complete. So later when
make_typename_type is called during the overload resolution of
f4(5, X<5>()), the "if (!dependent_scope_p (context))" succeeds and the
call to t = lookup_field (context, name, 2, /*want_type=*/true);
returns the field "type".

Tested for the c++ languages against trunk on
x86_64-unknown-linux-gnu. I am going launch a test for the other
languages right away.

-- 
	Dodji

commit 2c6d22fe7e4f00f2007a174437e2090f46188a19
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
    	(TEMPLATE_NUM_SIBLING_PARMS): New accessor.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(enum tsubst_flags)<tf_no_tpl_reduce>: New flag.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl.c (make_typename_type): Use uses_template_parms instead of
    	dependent_type_p.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (canonical_type_parameter): The canonical type of template
    	type params now takes in account the total number of
    	template parms of a given template. Use the new
    	TEMPLATE_NUM_SIBLING_PARMS accessor.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(current_template_args): Fix this for template template
    	parameters.
    	(tsubst_template_parm): Split out of ...
    	(tsubst_template_parms): ... this. Support the new
    	tf_no_tpl_reduce flag to avoid template parm level reduction on
    	demand.
    	(tsubst): Support the new tf_no_tpl_reduce flag. Use
    	TEMPLATE_NUM_SIBLING_PARMS.
    	(fixup_template_parms_canonical_types): New function. Uses
    	tsubst_template_parm.
    	(end_template_parm_list): Use it; compute the proper canonical
    	types for dependent types created during template parms parsing
    	and fixup those types accordingly. Set TEMPLATE_TYPE_PARM_SIBLING
    	on TEMPLATE_TEMPLATE_PARMs too.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(lookup_template_class): Make sure to require structural equality
    	for dependent types created during template parms parsing.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(type_dependent_expression_p): Do not crash on NULL expressions.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore.
    	(comp_template_parms_position): Re-indent. Take the length of
    	template parms list in account.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* g++.dg/template/typedef36.C: New test.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c594d6a..1537786 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6673,7 +6673,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c78beb7..cf936d2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3954,6 +3954,8 @@ enum tsubst_flags {
 				    when issuing other errors.   */
   /* Do not instantiate classes (used by count_non_default_template_args). */
   tf_no_class_instantiations = 1 << 8,
+  tf_no_tpl_reduce = 1 << 9,    /* Do not reduce the level of
+				   template parameters.  */
   /* Convenient substitution flags combinations.  */
   tf_warning_or_error = tf_warning | tf_error
 };
@@ -4321,10 +4323,13 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
+
+/* The length of the template parms list this template parm belongs
+   to. This is a an integer wrapped into a tree node.  */
+#define TEMPLATE_NUM_SIBLING_PARMS(NODE)			\
+  (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM,			\
+		TEMPLATE_TEMPLATE_PARM,				\
+		BOUND_TEMPLATE_TEMPLATE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5005,7 +5010,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5341,7 +5346,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 3d1420a..e4d39a8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3099,7 +3099,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
   else
     t = NULL_TREE;
 
-  if ((!t || TREE_CODE (t) == TREE_LIST) && dependent_type_p (context))
+  if ((!t || TREE_CODE (t) == TREE_LIST) && uses_template_parms (context))
     return build_typename_type (context, name, fullname, tag_type);
 
   want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 63197705..1c6bbbe 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 41feb57..a044659 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9385344..b8c35b3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10997,6 +10997,15 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms. Note that dependent
+     types created during this parsing require structural comparison
+     rather than canonical type comparison. This is because we first
+     need to know the total number of template parms to be able to
+     compute canonical types of each dependent type. So after the
+     loop, when we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11015,11 +11024,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5a90bdc..a4b13b1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -93,10 +93,14 @@ static GTY ((param_is (spec_entry)))
 static GTY ((param_is (spec_entry)))
   htab_t type_specializations;
 
-/* Contains canonical template parameter types. The vector is indexed by
-   the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
-   TREE_LIST, whose TREE_VALUEs contain the canonical template
-   parameters of various types and levels.  */
+/* Contains canonical template parameter types. The vector is indexed
+   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
+   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
+   total size of the template parameter list a given template
+   parameter would belong too, and whose TREE_VALUEs contain the
+   canonical template parameters of various types and levels,
+   belonging to a set of template parameters which size is
+   TREE_PURPOSE.  */
 static GTY(()) VEC(tree,gc) *canonical_template_parms;
 
 #define UNIFY_ALLOW_NONE 0
@@ -190,6 +194,9 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree current_template_args (void);
+static void fixup_template_parms_canonical_types (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3369,12 +3376,25 @@ build_template_parm_index (int index,
 
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
-   if no such parameter existed.  */
+   if no such parameter existed. TOTAL_NUM_PARMS is the number of
+   template parameters carried by the considered template.
+
+   If TYPE is the template parameter at position P in a
+   template, this function won't return the same canonical type as for
+   a another TYPE that would be a template parameter at position Q,
+   with Q != P.
+
+   If TOTAL_NUM_PARMS is 0, the function returns NULL_TREE.  */
+
 static tree
-canonical_type_parameter (tree type)
+canonical_type_parameter (tree type, unsigned total_num_parms)
 {
   tree list;
   int idx = TEMPLATE_TYPE_IDX (type);
+
+  if (total_num_parms == 0)
+    return NULL_TREE;
+
   if (!canonical_template_parms)
     canonical_template_parms = VEC_alloc (tree, gc, idx+1);
 
@@ -3382,15 +3402,20 @@ canonical_type_parameter (tree type)
     VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
 
   list = VEC_index (tree, canonical_template_parms, idx);
-  while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
-    list = TREE_CHAIN (list);
+  while (list)
+    {
+      if (TREE_INT_CST_LOW (TREE_PURPOSE (list)) == total_num_parms
+	  && comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+	break;
+      list = TREE_CHAIN (list);
+    }
 
   if (list)
     return TREE_VALUE (list);
   else
     {
       VEC_replace(tree, canonical_template_parms, idx,
-		  tree_cons (NULL_TREE, type, 
+		  tree_cons (size_int (total_num_parms), type, 
 			     VEC_index (tree, canonical_template_parms, idx)));
       return type;
     }
@@ -3438,15 +3463,21 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter can
+   be set to 0. Setting it to zero would create a template type
+   parameter with no canonical type.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3556,8 +3587,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 				     processing_template_decl,
 				     decl, TREE_TYPE (parm));
       TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
-      TYPE_CANONICAL (t) = canonical_type_parameter (t);
-    }
+      TYPE_CANONICAL (t) =
+	canonical_type_parameter (t, num_template_parms);
+   }
   DECL_ARTIFICIAL (decl) = 1;
   SET_DECL_TEMPLATE_PARM_P (decl);
   pushdecl (decl);
@@ -3573,9 +3605,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 tree
 end_template_parm_list (tree parms)
 {
-  int nparms;
+  int nparms, length = list_length (parms);
   tree parm, next;
-  tree saved_parmlist = make_tree_vec (list_length (parms));
+  tree saved_parmlist = make_tree_vec (length);
 
   current_template_parms
     = tree_cons (size_int (processing_template_decl),
@@ -3586,16 +3618,141 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
-	      current_template_parms;
+      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
+	  || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
+	TEMPLATE_NUM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
+	  size_int (length);
     }
 
+  fixup_template_parms_canonical_types ();
+
   --processing_template_parmlist;
 
   return saved_parmlist;
 }
 
+/* Walk current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static void
+fixup_template_parms_canonical_types (void)
+{
+  tree parm;
+  tree full_template_args;
+  tree parameter_vec;
+  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);
+
+  /* In this first loop, let's update the canonical type of each
+     type template parameter.  */
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree main_type, variant;
+
+      parm = TREE_VALUE (TREE_VEC_ELT (parameter_vec, i));
+      if (TREE_CODE (parm) == TYPE_DECL
+	  || TREE_CODE (parm) == TEMPLATE_DECL)
+	{
+	  if (TREE_CODE (parm) == TEMPLATE_DECL)
+	    {
+	      tree arglist = current_template_args ();
+	      tree tparms;
+	      int j;
+
+	      /* So PARM is a template tempate parameter, e.g, like TT
+		 in:
+
+		   template<class T, template<T> class TT> class S;
+		   
+		 In this case we want to substitute T into the
+		 template parameters of TT.
+
+		 Sot let's walk the template parms of PARM here, and
+		 tsubst ARGLIST into into each of the template
+		 parms.   */
+	      tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm));
+	      for (j = 0; j < TREE_VEC_LENGTH (tparms); ++j)
+		{
+		  tree substed_parm;
+		  ++cp_unevaluated_operand;
+		  /* Note the use of tf_no_tpl_reduce as the last
+		     argument to tsubst_template_parm here. Suppose
+		     the current template parameter of PARM is itself
+		     a template. In that case, we do not want
+		     tsubst_template_parm to reduce the level of the
+		     parameters of that later template , as tsubst or
+		     tsubst_template_parms would normally do [because
+		     we are not tsubsting here for the purpose of
+		     instantiating a type, rather, we just want to
+		     substitute template parameters "in
+		     place"]. Therefore, we use tf_no_tpl_reduce to
+		     really avoid that template parm level
+		     reduction.  */
+		  substed_parm = tsubst_template_parm (TREE_VEC_ELT (tparms, j),
+						       arglist, 
+						       tf_no_tpl_reduce);
+		  --cp_unevaluated_operand;
+		  TREE_VEC_ELT (tparms, j) = substed_parm;
+		}
+	    }
+
+	  /* Compute the canonical type of type template
+	     parameters and their variants.  */
+	  main_type = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+	  TYPE_CANONICAL (main_type) =
+	    canonical_type_parameter (main_type, num_parms);
+	  for (variant = TYPE_NEXT_VARIANT (main_type);
+	       variant;
+	       variant = TYPE_NEXT_VARIANT (variant))
+	    TYPE_CANONICAL (variant) =
+	      canonical_type_parameter (variant, num_parms);
+	}
+    }
+
+  /* And now let's substitute the template type parameters into
+     dependent non-type template arguments and default template
+     arguments.  */
+  full_template_args = current_template_args ();
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree cur = TREE_VEC_ELT (parameter_vec, i);
+
+      if ((TREE_CODE (parm) == TYPE_DECL
+	   || TREE_CODE (parm) == TEMPLATE_DECL)
+	  && TREE_PURPOSE (cur))
+	{
+	  tree default_arg = TREE_PURPOSE (cur);
+
+	  if (TYPE_P (default_arg)
+	      && !dependent_type_p (default_arg))
+	    continue;
+
+	  ++cp_unevaluated_operand;
+	  TREE_PURPOSE (cur) =
+	    tsubst_expr (default_arg, full_template_args,
+			 tf_none, default_arg, false);
+	  --cp_unevaluated_operand;
+	}
+
+      if (TREE_CODE (TREE_VALUE (cur)) == PARM_DECL)
+	{
+	  tree non_type_parm = TREE_VALUE (cur);
+	  ++cp_unevaluated_operand;
+	  TREE_VALUE (cur) =
+	    tsubst_decl (non_type_parm,
+			 full_template_args,
+			 tf_none);
+	  --cp_unevaluated_operand;
+	}
+    }
+}
+
 /* end_template_decl is called after a template declaration is seen.  */
 
 void
@@ -3706,7 +3863,23 @@ current_template_args (void)
       else
 	args = a;
     }
-
+  
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.
+      */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -6681,16 +6854,22 @@ lookup_template_class (tree d1,
 	  if (context == current_function_decl)
 	    pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
 
-	  if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
+	  if (any_template_arguments_need_structural_equality_p (arglist))
+	    /* Some of the template arguments require structural
+	       equality testing, so this template class requires
+	       structural equality testing. Note that we check this
+	       condition first because for dependent types that are
+	       created /during/ the parsing of template parameter lists,
+	       we must not require canonical type equality because
+	       canonical types of dependent types are actually going
+	       to be properly computed right at /the end/ of the
+	       template parms parsing.  */
+	    SET_TYPE_STRUCTURAL_EQUALITY (t);
+	  else if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
 	    /* This instantiation is another name for the primary
 	       template type. Set the TYPE_CANONICAL field
 	       appropriately. */
 	    TYPE_CANONICAL (t) = template_type;
-	  else if (any_template_arguments_need_structural_equality_p (arglist))
-	    /* Some of the template arguments require structural
-	       equality testing, so this template class requires
-	       structural equality testing. */
-	    SET_TYPE_STRUCTURAL_EQUALITY (t);
 	}
 
       /* If we called start_enum or pushtag above, this information
@@ -8722,6 +8901,7 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
 {
   tree r = NULL_TREE;
   tree* new_parms;
+  bool reduce_level_p = !(complain & tf_no_tpl_reduce);
 
   /* When substituting into a template, we must set
      PROCESSING_TEMPLATE_DECL as the template parameters may be
@@ -8730,19 +8910,18 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   ++processing_template_decl;
 
   for (new_parms = &r;
-       TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args);
+       ((reduce_level_p && TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args))
+	||(!reduce_level_p && parms));
        new_parms = &(TREE_CHAIN (*new_parms)),
 	 parms = TREE_CHAIN (parms))
     {
       tree new_vec =
 	make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
-      int i;
+      int i, new_level;
 
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
 	{
           tree tuple;
-          tree default_value;
-          tree parm_decl;
 
           if (parms == error_mark_node)
             continue;
@@ -8752,23 +8931,16 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
           if (tuple == error_mark_node)
             continue;
 
-          default_value = TREE_PURPOSE (tuple);
-          parm_decl = TREE_VALUE (tuple);
-
-	  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
-	  if (TREE_CODE (parm_decl) == PARM_DECL
-	      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
-	    parm_decl = error_mark_node;
-	  default_value = tsubst_template_arg (default_value, args,
-					       complain, NULL_TREE);
-
-	  tuple = build_tree_list (default_value, parm_decl);
-	  TREE_VEC_ELT (new_vec, i) = tuple;
+	  TREE_VEC_ELT (new_vec, i) =
+	    tsubst_template_parm (tuple, args, complain);
 	}
 
+      new_level = reduce_level_p
+	? TMPL_PARMS_DEPTH (parms) - TMPL_ARGS_DEPTH (args)
+	: TMPL_PARMS_DEPTH (parms);
+
       *new_parms =
-	tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
-			     - TMPL_ARGS_DEPTH (args)),
+	tree_cons (size_int (new_level),
 		   new_vec, NULL_TREE);
     }
 
@@ -8777,6 +8949,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Return the result of substituting ARGS into one template parameter
+   given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+   parameter and which TREE_PURPOSE is the default argument of the
+   template parameter.  */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+  tree default_value, parm_decl;
+
+  if (args == NULL_TREE
+      || t == NULL_TREE
+      || t == error_mark_node)
+    return t;
+
+  gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+  default_value = TREE_PURPOSE (t);
+  parm_decl = TREE_VALUE (t);
+
+  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+  if (TREE_CODE (parm_decl) == PARM_DECL
+      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+    parm_decl = error_mark_node;
+  default_value = tsubst_template_arg (default_value, args,
+				       complain, NULL_TREE);
+
+  return build_tree_list (default_value, parm_decl);
+}
+
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
@@ -10271,9 +10473,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	    else
 	      {
 		r = copy_type (t);
-		TEMPLATE_TYPE_PARM_INDEX (r)
-		  = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
-						r, levels, args, complain);
+		if (!(complain & tf_no_tpl_reduce))
+		  TEMPLATE_TYPE_PARM_INDEX (r)
+		    = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+						  r, levels, args, complain);
 		TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
 		TYPE_MAIN_VARIANT (r) = r;
 		TYPE_POINTER_TO (r) = NULL_TREE;
@@ -10291,7 +10494,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		else if (TYPE_STRUCTURAL_EQUALITY_P (t))
 		  SET_TYPE_STRUCTURAL_EQUALITY (r);
 		else
-		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
+		  {
+		    unsigned num_parms =
+		      (TEMPLATE_NUM_SIBLING_PARMS (t))
+		      ? TREE_INT_CST_LOW (TEMPLATE_NUM_SIBLING_PARMS (t))
+		      : 0;
+		    TYPE_CANONICAL (r) =
+		      canonical_type_parameter (r, num_parms);
+		  }
 
 		if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
 		  {
@@ -10307,7 +10517,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	    break;
 
 	  case TEMPLATE_PARM_INDEX:
-	    r = reduce_template_parm_level (t, type, levels, args, complain);
+	    if (complain & tf_no_tpl_reduce)
+	      r = t;
+	    else
+	      r = reduce_template_parm_level (t, type, levels, args, complain);
 	    break;
 
 	  default:
@@ -17786,7 +17999,8 @@ type_dependent_expression_p (tree expression)
   if (!processing_template_decl)
     return false;
 
-  if (expression == error_mark_node)
+  if (expression == error_mark_node
+      || expression == NULL_TREE)
     return false;
 
   /* An unresolved name is always dependent.  */
@@ -18406,7 +18620,7 @@ make_auto (void)
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
     (0, processing_template_decl + 1, processing_template_decl + 1,
      TYPE_NAME (au), NULL_TREE);
-  TYPE_CANONICAL (au) = canonical_type_parameter (au);
+  TYPE_CANONICAL (au) = canonical_type_parameter (au, 0);
   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 ea01d1f..580ebf3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1063,22 +1063,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index 0ac95d0..41aaca7 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,114 +1143,20 @@ comp_template_parms_position (tree t1, tree t2)
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
-
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* If T1 and T2 belong to template parm lists of different size,
+     let's assume they are different.  */
+  if (TEMPLATE_NUM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1))
+      != TEMPLATE_NUM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2)))
     return false;
 
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+      || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+      || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
+	  != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1295,12 +1201,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1345,6 +1245,7 @@ structural_comptypes (tree t1, tree t2, int strict)
 	  (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
 	   DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2))))
 	return false;
+
       if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
 	break;
       /* Don't check inheritance.  */
@@ -1401,8 +1302,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* If T1 and T2 don't have the same relative position in their
+	 template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+	return false;
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..f6155c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+#include <list>
+
+template<class T>
+class Test
+{
+protected:
+  typedef std::list<T> ListAlias;
+  ListAlias list;
+public:
+  typedef typename ListAlias::const_iterator const_iterator;
+  inline const_iterator begin() const;
+
+};
+
+template<class T>
+inline typename std::list<T>::const_iterator Test<T>::begin() const
+{
+  return list.begin();
+}
+

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-26 14:44                   ` Dodji Seketeli
@ 2010-09-26 15:10                     ` Jason Merrill
  2010-09-28 15:12                       ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Jason Merrill @ 2010-09-26 15:10 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

On 09/25/2010 11:19 AM, Dodji Seketeli wrote:
> Jason Merrill<jason@redhat.com>  writes:
>
> Sure. I'll post a separate patch for it once we are done with this one.
>
>>> +  if (total_num_parms == 0)
>>> +    return NULL_TREE;
>>
>> Since you're already treating parms from a list of unknown length as
>> distinct from parms from a list of known length, we can give them a
>> canonical type, too.
>
> Doing that doesn't seem to work. The problem is not with the comparison
> of type template parms but rather with the comparison of dependent types
> created during the template parms parsing.
>
> If type template parms don't require structural comparison then a type A
> (created during template parms parsing) dependent on those parms will
> have a canonical type.

Yep.

> The fixup then creates a type A' that is
> structurally equivalent to A, but has a different canonical type.

It shouldn't be structurally equivalent, since A's template parms come 
from a list of non-0 length, which is not true of A'.

> * Template parm level reduction.
>
> When at least one of the parms is itself a template [like in
> testsuite/g++.old-deja/g++.pt/nttp1.C] then at some point we end up in
> tsubst (at least) with an argument set that has a depth that is less
> than the depth of the parm of the template template parm we are
> susbtituting into.

Rather, the problem comes when we don't have any argument at all; in 
that case we reduce the level.

> My understanding is that the tsubsting code then thinks that we are
> doing the substitution for the purpose of instantiation and then reduces
> the level of the resulting parms.

Partial instantiation, yes.

I would expect that when we get to this point we've already done the 
fixup for these parms, so that they don't need to be substituted 
directly; we only need to fixup the type of any non-type parms (and so 
on recursively for template template parms).  That ought to avoid this 
problem.

> Incidentally I noticed that the tf_no_class_instantiation is not used by
> any client code anymore. Would you accept a patchlet to remove it?

Yep.

> During unification of C<5>  with X<5>  the argument 5 of X is converted
> into the type of the parameter of C, i.e 5 is converted into typename
> metafun<T>::type. convert_template_argument then tries to substitute
> into typename metafun<T>::type. This should just create another
> equivalent typename becase metafun<T>  is dependent and thus non
> complete. But when tsubst calls make_typename_type, the later fails to
> detect that metafun<T>  is dependent [because processing_template_decl is
> 0] and goes crazy.

Why don't we have an argument for T by this point?

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-26 15:10                     ` Jason Merrill
@ 2010-09-28 15:12                       ` Dodji Seketeli
  2010-09-28 15:15                         ` Dodji Seketeli
  2010-09-28 16:51                         ` Jason Merrill
  0 siblings, 2 replies; 38+ messages in thread
From: Dodji Seketeli @ 2010-09-28 15:12 UTC (permalink / raw)
  To: Jason Merrill; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

[...]
>>>> +  if (total_num_parms == 0)
>>>> +    return NULL_TREE;
>>>
>>> Since you're already treating parms from a list of unknown length as
>>> distinct from parms from a list of known length, we can give them a
>>> canonical type, too.
>>
>> Doing that doesn't seem to work. The problem is not with the comparison
>> of type template parms but rather with the comparison of dependent types
>> created during the template parms parsing.
>>
>> If type template parms don't require structural comparison then a type A
>> (created during template parms parsing) dependent on those parms will
>> have a canonical type.
>
> Yep.
>
>> The fixup then creates a type A' that is
>> structurally equivalent to A, but has a different canonical type.
>
> It shouldn't be structurally equivalent, since A's template parms come
> from a list of non-0 length, which is not true of A'.
>

I must be missing something. In structural_comptype, in the RECORD_TYPE
case, comp_template_args is called and I think this eventually compares
the template parms of A and A' using their canonical types, even though
we are calling from structural_comptype and are supposed to do
structural comparison. Hence A and A' will is considered structurally
equivalent. No?

>> * Template parm level reduction.
>>
>> When at least one of the parms is itself a template [like in
>> testsuite/g++.old-deja/g++.pt/nttp1.C] then at some point we end up in
>> tsubst (at least) with an argument set that has a depth that is less
>> than the depth of the parm of the template template parm we are
>> susbtituting into.
>
> Rather, the problem comes when we don't have any argument at all; in
> that case we reduce the level.
>
>> My understanding is that the tsubsting code then thinks that we are
>> doing the substitution for the purpose of instantiation and then reduces
>> the level of the resulting parms.
>
> Partial instantiation, yes.
>
> I would expect that when we get to this point we've already done the
> fixup for these parms, so that they don't need to be substituted
> directly; we only need to fixup the type of any non-type parms (and so
> on recursively for template template parms).  That ought to avoid this
> problem.

Just to be sure I understand; do you mean I should write a function that
recursively does type substitution for non-type parms (only) of template
template parms and use that in the fixup? Or does such a function exists
already?

[...]

>
>> Incidentally I noticed that the tf_no_class_instantiation is not used by
>> any client code anymore. Would you accept a patchlet to remove it?
>
> Yep.
>
>> During unification of C<5>  with X<5>  the argument 5 of X is converted
>> into the type of the parameter of C, i.e 5 is converted into typename
>> metafun<T>::type. convert_template_argument then tries to substitute
>> into typename metafun<T>::type. This should just create another
>> equivalent typename becase metafun<T>  is dependent and thus non
>> complete. But when tsubst calls make_typename_type, the later fails to
>> detect that metafun<T>  is dependent [because processing_template_decl is
>> 0] and goes crazy.
>
> Why don't we have an argument for T by this point?

Good question. I seems T's argument is "lost" somehow even in current
trunk without my patch. I think what happens is that unify (in the
BOUND_TEMPLATE_TEMPLATE_PARM case) calls coerce_template_parms with an
argvec that is just the innermost template arguments of C<5>, which is
{5}. I think it should call it with the full set of template arguments
including the arguments deduced so far i.e, {{5}, {5}}. The depth of
that full set would be 2. The first level of arguments is the argument
for T (the first {5}), and the second set (the second {5}) would be
to unified with "metafun<5>::type" to deduce "int".

This hunk -- similar to what is done in lookup_template_class in the
"if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))" branch -- seems to fix the
issue:

~=~
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e060cc7..bf13978 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14914,6 +14914,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  {
 	    tree parmvec = TYPE_TI_ARGS (parm);
 	    tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+	    tree full_argvec = add_to_template_args (targs, argvec);
 	    tree parm_parms 
               = DECL_INNERMOST_TEMPLATE_PARMS
 	          (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14948,7 +14949,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	      the global operator+ will be used; if they are not, the
 	      Lvalue_proxy will be converted to float.  */
 	    if (coerce_template_parms (parm_parms,
-                                       argvec,
+                                       full_argvec,
 				       TYPE_TI_TEMPLATE (parm),
 				       tf_none,
 				       /*require_all_args=*/true,
~=~

I have removed the use of use_template_parms in make_typename_type from
make_typename_type thus. Does this make more sense?

Thanks.
-- 
	Dodji

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-28 15:12                       ` Dodji Seketeli
@ 2010-09-28 15:15                         ` Dodji Seketeli
  2010-09-28 16:51                         ` Jason Merrill
  1 sibling, 0 replies; 38+ messages in thread
From: Dodji Seketeli @ 2010-09-28 15:15 UTC (permalink / raw)
  To: Jason Merrill; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

In my previous email, I forgot to insert the fully updated patch. Here
it is.

-- 
	Dodji

commit e70dd9a7c4a3008133243597735e3698c5f5626a
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
    	(TEMPLATE_NUM_SIBLING_PARMS): New accessor.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(enum tsubst_flags)<tf_no_tpl_reduce>: New flag.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (canonical_type_parameter): The canonical type of template
    	type params now takes in account the total number of
    	template parms of a given template. Use the new
    	TEMPLATE_NUM_SIBLING_PARMS accessor.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(current_template_args): Fix this for template template
    	parameters.
    	(tsubst_template_parm): Split out of ...
    	(tsubst_template_parms): ... this. Support the new
    	tf_no_tpl_reduce flag to avoid template parm level reduction on
    	demand.
    	(tsubst): Support the new tf_no_tpl_reduce flag. Use
    	TEMPLATE_NUM_SIBLING_PARMS.
    	(fixup_template_parms_canonical_types): New function. Uses
    	tsubst_template_parm.
    	(end_template_parm_list): Use it; compute the proper canonical
    	types for dependent types created during template parms parsing
    	and fixup those types accordingly. Set TEMPLATE_TYPE_PARM_SIBLING
    	on TEMPLATE_TEMPLATE_PARMs too.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(lookup_template_class): Make sure to require structural equality
    	for dependent types created during template parms parsing.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(type_dependent_expression_p): Do not crash on NULL expressions.
    	(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
    	using all the arguments deduced so far.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore.
    	(comp_template_parms_position): Re-indent. Take the length of
    	template parms list in account.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* g++.dg/template/typedef36.C: New test.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c594d6a..1537786 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6673,7 +6673,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c78beb7..cf936d2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3954,6 +3954,8 @@ enum tsubst_flags {
 				    when issuing other errors.   */
   /* Do not instantiate classes (used by count_non_default_template_args). */
   tf_no_class_instantiations = 1 << 8,
+  tf_no_tpl_reduce = 1 << 9,    /* Do not reduce the level of
+				   template parameters.  */
   /* Convenient substitution flags combinations.  */
   tf_warning_or_error = tf_warning | tf_error
 };
@@ -4321,10 +4323,13 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
+
+/* The length of the template parms list this template parm belongs
+   to. This is a an integer wrapped into a tree node.  */
+#define TEMPLATE_NUM_SIBLING_PARMS(NODE)			\
+  (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM,			\
+		TEMPLATE_TEMPLATE_PARM,				\
+		BOUND_TEMPLATE_TEMPLATE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5005,7 +5010,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5341,7 +5346,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 63197705..1c6bbbe 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 41feb57..a044659 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9385344..b8c35b3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10997,6 +10997,15 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms. Note that dependent
+     types created during this parsing require structural comparison
+     rather than canonical type comparison. This is because we first
+     need to know the total number of template parms to be able to
+     compute canonical types of each dependent type. So after the
+     loop, when we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11015,11 +11024,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f5e09ee..bf13978 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -93,10 +93,14 @@ static GTY ((param_is (spec_entry)))
 static GTY ((param_is (spec_entry)))
   htab_t type_specializations;
 
-/* Contains canonical template parameter types. The vector is indexed by
-   the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
-   TREE_LIST, whose TREE_VALUEs contain the canonical template
-   parameters of various types and levels.  */
+/* Contains canonical template parameter types. The vector is indexed
+   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
+   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
+   total size of the template parameter list a given template
+   parameter would belong too, and whose TREE_VALUEs contain the
+   canonical template parameters of various types and levels,
+   belonging to a set of template parameters which size is
+   TREE_PURPOSE.  */
 static GTY(()) VEC(tree,gc) *canonical_template_parms;
 
 #define UNIFY_ALLOW_NONE 0
@@ -190,6 +194,9 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree current_template_args (void);
+static void fixup_template_parms_canonical_types (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3369,12 +3376,25 @@ build_template_parm_index (int index,
 
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
-   if no such parameter existed.  */
+   if no such parameter existed. TOTAL_NUM_PARMS is the number of
+   template parameters carried by the considered template.
+
+   If TYPE is the template parameter at position P in a
+   template, this function won't return the same canonical type as for
+   a another TYPE that would be a template parameter at position Q,
+   with Q != P.
+
+   If TOTAL_NUM_PARMS is 0, the function returns NULL_TREE.  */
+
 static tree
-canonical_type_parameter (tree type)
+canonical_type_parameter (tree type, unsigned total_num_parms)
 {
   tree list;
   int idx = TEMPLATE_TYPE_IDX (type);
+
+  if (total_num_parms == 0)
+    return NULL_TREE;
+
   if (!canonical_template_parms)
     canonical_template_parms = VEC_alloc (tree, gc, idx+1);
 
@@ -3382,15 +3402,20 @@ canonical_type_parameter (tree type)
     VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
 
   list = VEC_index (tree, canonical_template_parms, idx);
-  while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
-    list = TREE_CHAIN (list);
+  while (list)
+    {
+      if (TREE_INT_CST_LOW (TREE_PURPOSE (list)) == total_num_parms
+	  && comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+	break;
+      list = TREE_CHAIN (list);
+    }
 
   if (list)
     return TREE_VALUE (list);
   else
     {
       VEC_replace(tree, canonical_template_parms, idx,
-		  tree_cons (NULL_TREE, type, 
+		  tree_cons (size_int (total_num_parms), type, 
 			     VEC_index (tree, canonical_template_parms, idx)));
       return type;
     }
@@ -3438,15 +3463,21 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter can
+   be set to 0. Setting it to zero would create a template type
+   parameter with no canonical type.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3556,8 +3587,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 				     processing_template_decl,
 				     decl, TREE_TYPE (parm));
       TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
-      TYPE_CANONICAL (t) = canonical_type_parameter (t);
-    }
+      TYPE_CANONICAL (t) =
+	canonical_type_parameter (t, num_template_parms);
+   }
   DECL_ARTIFICIAL (decl) = 1;
   SET_DECL_TEMPLATE_PARM_P (decl);
   pushdecl (decl);
@@ -3573,9 +3605,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 tree
 end_template_parm_list (tree parms)
 {
-  int nparms;
+  int nparms, length = list_length (parms);
   tree parm, next;
-  tree saved_parmlist = make_tree_vec (list_length (parms));
+  tree saved_parmlist = make_tree_vec (length);
 
   current_template_parms
     = tree_cons (size_int (processing_template_decl),
@@ -3586,16 +3618,141 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
-	      current_template_parms;
+      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
+	  || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
+	TEMPLATE_NUM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
+	  size_int (length);
     }
 
+  fixup_template_parms_canonical_types ();
+
   --processing_template_parmlist;
 
   return saved_parmlist;
 }
 
+/* Walk current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static void
+fixup_template_parms_canonical_types (void)
+{
+  tree parm;
+  tree full_template_args;
+  tree parameter_vec;
+  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);
+
+  /* In this first loop, let's update the canonical type of each
+     type template parameter.  */
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree main_type, variant;
+
+      parm = TREE_VALUE (TREE_VEC_ELT (parameter_vec, i));
+      if (TREE_CODE (parm) == TYPE_DECL
+	  || TREE_CODE (parm) == TEMPLATE_DECL)
+	{
+	  if (TREE_CODE (parm) == TEMPLATE_DECL)
+	    {
+	      tree arglist = current_template_args ();
+	      tree tparms;
+	      int j;
+
+	      /* So PARM is a template tempate parameter, e.g, like TT
+		 in:
+
+		   template<class T, template<T> class TT> class S;
+		   
+		 In this case we want to substitute T into the
+		 template parameters of TT.
+
+		 Sot let's walk the template parms of PARM here, and
+		 tsubst ARGLIST into into each of the template
+		 parms.   */
+	      tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm));
+	      for (j = 0; j < TREE_VEC_LENGTH (tparms); ++j)
+		{
+		  tree substed_parm;
+		  ++cp_unevaluated_operand;
+		  /* Note the use of tf_no_tpl_reduce as the last
+		     argument to tsubst_template_parm here. Suppose
+		     the current template parameter of PARM is itself
+		     a template. In that case, we do not want
+		     tsubst_template_parm to reduce the level of the
+		     parameters of that later template , as tsubst or
+		     tsubst_template_parms would normally do [because
+		     we are not tsubsting here for the purpose of
+		     instantiating a type, rather, we just want to
+		     substitute template parameters "in
+		     place"]. Therefore, we use tf_no_tpl_reduce to
+		     really avoid that template parm level
+		     reduction.  */
+		  substed_parm = tsubst_template_parm (TREE_VEC_ELT (tparms, j),
+						       arglist, 
+						       tf_no_tpl_reduce);
+		  --cp_unevaluated_operand;
+		  TREE_VEC_ELT (tparms, j) = substed_parm;
+		}
+	    }
+
+	  /* Compute the canonical type of type template
+	     parameters and their variants.  */
+	  main_type = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+	  TYPE_CANONICAL (main_type) =
+	    canonical_type_parameter (main_type, num_parms);
+	  for (variant = TYPE_NEXT_VARIANT (main_type);
+	       variant;
+	       variant = TYPE_NEXT_VARIANT (variant))
+	    TYPE_CANONICAL (variant) =
+	      canonical_type_parameter (variant, num_parms);
+	}
+    }
+
+  /* And now let's substitute the template type parameters into
+     dependent non-type template arguments and default template
+     arguments.  */
+  full_template_args = current_template_args ();
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree cur = TREE_VEC_ELT (parameter_vec, i);
+
+      if ((TREE_CODE (parm) == TYPE_DECL
+	   || TREE_CODE (parm) == TEMPLATE_DECL)
+	  && TREE_PURPOSE (cur))
+	{
+	  tree default_arg = TREE_PURPOSE (cur);
+
+	  if (TYPE_P (default_arg)
+	      && !dependent_type_p (default_arg))
+	    continue;
+
+	  ++cp_unevaluated_operand;
+	  TREE_PURPOSE (cur) =
+	    tsubst_expr (default_arg, full_template_args,
+			 tf_none, default_arg, false);
+	  --cp_unevaluated_operand;
+	}
+
+      if (TREE_CODE (TREE_VALUE (cur)) == PARM_DECL)
+	{
+	  tree non_type_parm = TREE_VALUE (cur);
+	  ++cp_unevaluated_operand;
+	  TREE_VALUE (cur) =
+	    tsubst_decl (non_type_parm,
+			 full_template_args,
+			 tf_none);
+	  --cp_unevaluated_operand;
+	}
+    }
+}
+
 /* end_template_decl is called after a template declaration is seen.  */
 
 void
@@ -3706,7 +3863,23 @@ current_template_args (void)
       else
 	args = a;
     }
-
+  
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.
+      */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -6681,16 +6854,22 @@ lookup_template_class (tree d1,
 	  if (context == current_function_decl)
 	    pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
 
-	  if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
+	  if (any_template_arguments_need_structural_equality_p (arglist))
+	    /* Some of the template arguments require structural
+	       equality testing, so this template class requires
+	       structural equality testing. Note that we check this
+	       condition first because for dependent types that are
+	       created /during/ the parsing of template parameter lists,
+	       we must not require canonical type equality because
+	       canonical types of dependent types are actually going
+	       to be properly computed right at /the end/ of the
+	       template parms parsing.  */
+	    SET_TYPE_STRUCTURAL_EQUALITY (t);
+	  else if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
 	    /* This instantiation is another name for the primary
 	       template type. Set the TYPE_CANONICAL field
 	       appropriately. */
 	    TYPE_CANONICAL (t) = template_type;
-	  else if (any_template_arguments_need_structural_equality_p (arglist))
-	    /* Some of the template arguments require structural
-	       equality testing, so this template class requires
-	       structural equality testing. */
-	    SET_TYPE_STRUCTURAL_EQUALITY (t);
 	}
 
       /* If we called start_enum or pushtag above, this information
@@ -8722,6 +8901,7 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
 {
   tree r = NULL_TREE;
   tree* new_parms;
+  bool reduce_level_p = !(complain & tf_no_tpl_reduce);
 
   /* When substituting into a template, we must set
      PROCESSING_TEMPLATE_DECL as the template parameters may be
@@ -8730,19 +8910,18 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   ++processing_template_decl;
 
   for (new_parms = &r;
-       TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args);
+       ((reduce_level_p && TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args))
+	||(!reduce_level_p && parms));
        new_parms = &(TREE_CHAIN (*new_parms)),
 	 parms = TREE_CHAIN (parms))
     {
       tree new_vec =
 	make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
-      int i;
+      int i, new_level;
 
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
 	{
           tree tuple;
-          tree default_value;
-          tree parm_decl;
 
           if (parms == error_mark_node)
             continue;
@@ -8752,23 +8931,16 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
           if (tuple == error_mark_node)
             continue;
 
-          default_value = TREE_PURPOSE (tuple);
-          parm_decl = TREE_VALUE (tuple);
-
-	  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
-	  if (TREE_CODE (parm_decl) == PARM_DECL
-	      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
-	    parm_decl = error_mark_node;
-	  default_value = tsubst_template_arg (default_value, args,
-					       complain, NULL_TREE);
-
-	  tuple = build_tree_list (default_value, parm_decl);
-	  TREE_VEC_ELT (new_vec, i) = tuple;
+	  TREE_VEC_ELT (new_vec, i) =
+	    tsubst_template_parm (tuple, args, complain);
 	}
 
+      new_level = reduce_level_p
+	? TMPL_PARMS_DEPTH (parms) - TMPL_ARGS_DEPTH (args)
+	: TMPL_PARMS_DEPTH (parms);
+
       *new_parms =
-	tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
-			     - TMPL_ARGS_DEPTH (args)),
+	tree_cons (size_int (new_level),
 		   new_vec, NULL_TREE);
     }
 
@@ -8777,6 +8949,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Return the result of substituting ARGS into one template parameter
+   given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+   parameter and which TREE_PURPOSE is the default argument of the
+   template parameter.  */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+  tree default_value, parm_decl;
+
+  if (args == NULL_TREE
+      || t == NULL_TREE
+      || t == error_mark_node)
+    return t;
+
+  gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+  default_value = TREE_PURPOSE (t);
+  parm_decl = TREE_VALUE (t);
+
+  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+  if (TREE_CODE (parm_decl) == PARM_DECL
+      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+    parm_decl = error_mark_node;
+  default_value = tsubst_template_arg (default_value, args,
+				       complain, NULL_TREE);
+
+  return build_tree_list (default_value, parm_decl);
+}
+
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
@@ -10271,9 +10473,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	    else
 	      {
 		r = copy_type (t);
-		TEMPLATE_TYPE_PARM_INDEX (r)
-		  = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
-						r, levels, args, complain);
+		if (!(complain & tf_no_tpl_reduce))
+		  TEMPLATE_TYPE_PARM_INDEX (r)
+		    = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+						  r, levels, args, complain);
 		TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
 		TYPE_MAIN_VARIANT (r) = r;
 		TYPE_POINTER_TO (r) = NULL_TREE;
@@ -10291,7 +10494,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		else if (TYPE_STRUCTURAL_EQUALITY_P (t))
 		  SET_TYPE_STRUCTURAL_EQUALITY (r);
 		else
-		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
+		  {
+		    unsigned num_parms =
+		      (TEMPLATE_NUM_SIBLING_PARMS (t))
+		      ? TREE_INT_CST_LOW (TEMPLATE_NUM_SIBLING_PARMS (t))
+		      : 0;
+		    TYPE_CANONICAL (r) =
+		      canonical_type_parameter (r, num_parms);
+		  }
 
 		if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
 		  {
@@ -10307,7 +10517,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	    break;
 
 	  case TEMPLATE_PARM_INDEX:
-	    r = reduce_template_parm_level (t, type, levels, args, complain);
+	    if (complain & tf_no_tpl_reduce)
+	      r = t;
+	    else
+	      r = reduce_template_parm_level (t, type, levels, args, complain);
 	    break;
 
 	  default:
@@ -14701,6 +14914,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  {
 	    tree parmvec = TYPE_TI_ARGS (parm);
 	    tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+	    tree full_argvec = add_to_template_args (targs, argvec);
 	    tree parm_parms 
               = DECL_INNERMOST_TEMPLATE_PARMS
 	          (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14735,7 +14949,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	      the global operator+ will be used; if they are not, the
 	      Lvalue_proxy will be converted to float.  */
 	    if (coerce_template_parms (parm_parms,
-                                       argvec,
+                                       full_argvec,
 				       TYPE_TI_TEMPLATE (parm),
 				       tf_none,
 				       /*require_all_args=*/true,
@@ -17781,7 +17995,8 @@ type_dependent_expression_p (tree expression)
   if (!processing_template_decl)
     return false;
 
-  if (expression == error_mark_node)
+  if (expression == error_mark_node
+      || expression == NULL_TREE)
     return false;
 
   /* An unresolved name is always dependent.  */
@@ -18401,7 +18616,7 @@ make_auto (void)
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
     (0, processing_template_decl + 1, processing_template_decl + 1,
      TYPE_NAME (au), NULL_TREE);
-  TYPE_CANONICAL (au) = canonical_type_parameter (au);
+  TYPE_CANONICAL (au) = canonical_type_parameter (au, 0);
   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 ea01d1f..580ebf3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1063,22 +1063,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index 019c51e..5238a01 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,114 +1143,20 @@ comp_template_parms_position (tree t1, tree t2)
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
-
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* If T1 and T2 belong to template parm lists of different size,
+     let's assume they are different.  */
+  if (TEMPLATE_NUM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1))
+      != TEMPLATE_NUM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2)))
     return false;
 
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+      || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+      || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
+	  != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1295,12 +1201,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1345,6 +1245,7 @@ structural_comptypes (tree t1, tree t2, int strict)
 	  (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
 	   DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2))))
 	return false;
+
       if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
 	break;
       /* Don't check inheritance.  */
@@ -1401,8 +1302,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* If T1 and T2 don't have the same relative position in their
+	 template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+	return false;
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..f6155c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+#include <list>
+
+template<class T>
+class Test
+{
+protected:
+  typedef std::list<T> ListAlias;
+  ListAlias list;
+public:
+  typedef typename ListAlias::const_iterator const_iterator;
+  inline const_iterator begin() const;
+
+};
+
+template<class T>
+inline typename std::list<T>::const_iterator Test<T>::begin() const
+{
+  return list.begin();
+}
+

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-28 15:12                       ` Dodji Seketeli
  2010-09-28 15:15                         ` Dodji Seketeli
@ 2010-09-28 16:51                         ` Jason Merrill
  2010-09-30  8:55                           ` Dodji Seketeli
  1 sibling, 1 reply; 38+ messages in thread
From: Jason Merrill @ 2010-09-28 16:51 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

On 09/28/2010 07:25 AM, Dodji Seketeli wrote:
> I must be missing something. In structural_comptype, in the RECORD_TYPE
> case, comp_template_args is called and I think this eventually compares
> the template parms of A and A' using their canonical types, even though
> we are calling from structural_comptype and are supposed to do
> structural comparison.

Right.

> Hence A and A' will is considered structurally
> equivalent. No?

I don't see why; the template parms of A and A' should have different 
canonical types.

> Just to be sure I understand; do you mean I should write a function that
> recursively does type substitution for non-type parms (only) of template
> template parms and use that in the fixup? Or does such a function exists
> already?

The former.  Or rather, that fixup_template_parms_canonical_types should 
work this way.  Incidentally, I notice that it still does two passes 
over the parm list.

> This hunk -- similar to what is done in lookup_template_class in the
> "if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))" branch -- seems to fix the
> issue:

Looks good.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-28 16:51                         ` Jason Merrill
@ 2010-09-30  8:55                           ` Dodji Seketeli
  2010-09-30  9:10                             ` Jason Merrill
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-09-30  8:55 UTC (permalink / raw)
  To: Jason Merrill; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 09/28/2010 07:25 AM, Dodji Seketeli wrote:
>> I must be missing something. In structural_comptype, in the RECORD_TYPE
>> case, comp_template_args is called and I think this eventually compares
>> the template parms of A and A' using their canonical types, even though
>> we are calling from structural_comptype and are supposed to do
>> structural comparison.
>
> Right.
>
>> Hence A and A' will is considered structurally
>> equivalent. No?
>
> I don't see why; the template parms of A and A' should have different
> canonical types.

Ah, I wasn't clear. During the fixup, at some point, A and A' have the
same template parm actually. Because A's template parm (let's call it T)
saw its canonical type updated, and then, T got substituted into A to
create A'.

But then A kept its canonical type, even thoug T's canonical type
changed. And A' has another canonical type, different from the one of A.

>
>> Just to be sure I understand; do you mean I should write a function that
>> recursively does type substitution for non-type parms (only) of template
>> template parms and use that in the fixup? Or does such a function exists
>> already?
>
> The former.  Or rather, that fixup_template_parms_canonical_types
> should work this way.

Okay, thanks, working on that now.

>  Incidentally, I notice that it still does two
> passes over the parm list.

Oops, okay I will address that.

-- 
	Dodji

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-30  8:55                           ` Dodji Seketeli
@ 2010-09-30  9:10                             ` Jason Merrill
  2010-10-06 18:53                               ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Jason Merrill @ 2010-09-30  9:10 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

On 09/29/2010 03:05 PM, Dodji Seketeli wrote:
> Ah, I wasn't clear. During the fixup, at some point, A and A' have the
> same template parm actually. Because A's template parm (let's call it T)
> saw its canonical type updated

Well, that's the problem then.  You shouldn't be modifying the template 
parms that you started out with, you should be replacing them with new ones.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-09-30  9:10                             ` Jason Merrill
@ 2010-10-06 18:53                               ` Dodji Seketeli
  2010-10-06 22:15                                 ` Paolo Carlini
  2010-10-07 18:30                                 ` Jason Merrill
  0 siblings, 2 replies; 38+ messages in thread
From: Dodji Seketeli @ 2010-10-06 18:53 UTC (permalink / raw)
  To: Jason Merrill; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

Hello,

Following your comments here is a new version of the patch.

The main changes are the following:

* the list of template parms is walked only once for the fixup.

* following our discussion offline I moved the sibbling parms number
  moved to TEMPLATE_PARM_INDEX. I created a new field in struct
  template_parm_index_s for that because I couldn't find another free
  slot. Maybe you'd have an idea to avoid adding this field here.

* to substitute fixed-up template type parameters into parameters of
  template template parameters, I tried hard to build the full set of
  template parameters to avoid triggering partial instantiation. E,g:

  template<class T> //#0
  struct S
  {
    template<template<class U, T a> class TPL> void foo(T t); // #1<-- here
  };

  When substituting the fixed up T of #0 into the a parameter in #1, I
  use the following set of template parms as argument to tsubst:
  {{T}, {TPL}, {U, T}}. This is similar to what is done in
  lookup_template_class when the D1 parameter of that function is a
  template template parm. This way I could do away with the
  tf_no_tpl_reduce flag I introduced in the previous version of the
  patch.

* when fixing up a template type parms T, make sure subsequent name
  lookups of T return the fixed up T. Not the pre-fixup one. That
  basically means that I set the TREE_TYPE of of the TYPE_NAME of the
  pre-fixup T to the fixedup T.

  I do a similar trick for non-type template parms too. E,g, consider this:

  template<class T, T u> //#0
  auto foo(T t) -> decltype(u); //#1

  After fixup, I want lookups of u at #1 to return references to the
  fixedup T, not to the pre-fixup one.

* canonical_type_parameter doesn't return NULL_TREE anymore.

Tested on x86_64-unknown-linux-gnu against trunk.

-- 
	Dodji

commit 6ea4303e231bc99e1fc6c04365358a861434a2a7
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for dependent typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
    	(struct template_parm_index_s)<num_siblings>: New field.
    	(TEMPLATE_NUM_SIBLING_PARMS): New accessor. The sibbling parms
    	number is now carried by TEMPLATE_PARM_INDEX.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	(get_template_parms_num_siblings)
    	(set_template_parms_num_siblings): Declare new accessors.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
    	(fixup_template_parms): New private functions.
    	(get_template_parms_num_siblings)
    	(set_template_parms_num_siblings): New public functions.
    	(canonical_type_parameter): The canonical type of template type
    	params now takes in account the total number of template parms of
    	a given template.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(current_template_args): Fix this for template template
    	parameters.
    	(tsubst_template_parm): Split out of ...
    	(tsubst_template_parms): ... this.
    	(reduce_template_parm_level): Don't loose
    	TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
    	(template_parm_to_arg): Extracted this function ...
    	(current_template_args): ... from this one.
    	(end_template_parm_list): Do not update template sibling parms
    	here anymore. Use fixup_template_parms instead.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(type_dependent_expression_p): Do not crash on NULL expressions.
    	(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
    	using all the arguments deduced so far.
    	(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
    	canonical_type_parameter.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore.
    	(comp_template_parms_position): Re-indent. Take the length of
    	template parms list in account.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* g++.dg/template/typedef36.C: New test.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b093ce0..1c4e368 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6671,7 +6671,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index aa1fe4d..0703a89 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -236,6 +236,7 @@ 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;
@@ -4300,6 +4301,9 @@ 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)
@@ -4321,10 +4325,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5005,7 +5005,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5091,6 +5091,8 @@ extern tree get_template_innermost_arguments	(const_tree);
 extern tree get_template_argument_pack_elems	(const_tree);
 extern tree get_function_template_decl		(const_tree);
 extern tree resolve_nondeduced_context		(tree);
+extern int get_template_parms_num_siblings      (tree);
+extern void set_template_parms_num_siblings     (tree, int);
 
 /* in repo.c */
 extern void init_repo				(void);
@@ -5341,7 +5343,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index fcc83fb..3ba2a28 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index e980cb6..5889adc 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 82026b1..240d546 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11011,6 +11011,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms.  We first need to know
+     the total number of template parms to be able to compute proper
+     canonical types of each dependent type. So after the loop, when
+     we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11029,11 +11036,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index eabd11b..c6e8798 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -93,10 +93,14 @@ static GTY ((param_is (spec_entry)))
 static GTY ((param_is (spec_entry)))
   htab_t type_specializations;
 
-/* Contains canonical template parameter types. The vector is indexed by
-   the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
-   TREE_LIST, whose TREE_VALUEs contain the canonical template
-   parameters of various types and levels.  */
+/* Contains canonical template parameter types. The vector is indexed
+   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
+   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
+   total size of the template parameter list a given template
+   parameter would belong too, and whose TREE_VALUEs contain the
+   canonical template parameters of various types and levels,
+   belonging to a set of template parameters which size is
+   TREE_PURPOSE.  */
 static GTY(()) VEC(tree,gc) *canonical_template_parms;
 
 #define UNIFY_ALLOW_NONE 0
@@ -190,6 +194,12 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree template_parm_to_arg (tree t);
+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 void fixup_template_parms (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3369,9 +3379,19 @@ build_template_parm_index (int index,
 
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
-   if no such parameter existed.  */
+   if no such parameter existed. TOTAL_NUM_PARMS is the number of
+   template parameters carried by the considered template.
+
+   If TYPE is the template parameter at position P in a
+   template, this function won't return the same canonical type as for
+   a another TYPE that would be a template parameter at position Q,
+   with Q != P.
+
+   If TOTAL_NUM_PARMS is 0, it means the number of template parms is
+   not known yet, e.g, we are still parsing the template parms list.  */
+
 static tree
-canonical_type_parameter (tree type)
+canonical_type_parameter (tree type, unsigned total_num_parms)
 {
   tree list;
   int idx = TEMPLATE_TYPE_IDX (type);
@@ -3382,15 +3402,20 @@ canonical_type_parameter (tree type)
     VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
 
   list = VEC_index (tree, canonical_template_parms, idx);
-  while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
-    list = TREE_CHAIN (list);
+  while (list)
+    {
+      if (TREE_INT_CST_LOW (TREE_PURPOSE (list)) == total_num_parms
+	  && comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+	break;
+      list = TREE_CHAIN (list);
+    }
 
   if (list)
     return TREE_VALUE (list);
   else
     {
       VEC_replace(tree, canonical_template_parms, idx,
-		  tree_cons (NULL_TREE, type, 
+		  tree_cons (size_int (total_num_parms), type, 
 			     VEC_index (tree, canonical_template_parms, idx)));
       return type;
     }
@@ -3425,6 +3450,7 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
 				     TEMPLATE_PARM_ORIG_LEVEL (index),
 				     decl, type);
       TEMPLATE_PARM_DESCENDANTS (index) = t;
+      TEMPLATE_PARM_NUM_SIBLINGS (t) = TEMPLATE_PARM_NUM_SIBLINGS (index);
       TEMPLATE_PARM_PARAMETER_PACK (t) 
 	= TEMPLATE_PARM_PARAMETER_PACK (index);
 
@@ -3438,15 +3464,21 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter can
+   be set to 0. Setting it to zero would create a template type
+   parameter with no canonical type.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3556,8 +3588,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 				     processing_template_decl,
 				     decl, TREE_TYPE (parm));
       TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
-      TYPE_CANONICAL (t) = canonical_type_parameter (t);
-    }
+      TYPE_CANONICAL (t) =
+	canonical_type_parameter (t, num_template_parms);
+   }
   DECL_ARTIFICIAL (decl) = 1;
   SET_DECL_TEMPLATE_PARM_P (decl);
   pushdecl (decl);
@@ -3573,9 +3606,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 tree
 end_template_parm_list (tree parms)
 {
-  int nparms;
+  int nparms, length = list_length (parms);
   tree parm, next;
-  tree saved_parmlist = make_tree_vec (list_length (parms));
+  tree saved_parmlist = make_tree_vec (length);
 
   current_template_parms
     = tree_cons (size_int (processing_template_decl),
@@ -3586,16 +3619,305 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
-	      current_template_parms;
     }
 
+  fixup_template_parms ();
+
   --processing_template_parmlist;
 
   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 = copy_type (type);
+  /* 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 = 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),
+				   decl, t);
+  TEMPLATE_PARM_DESCENDANTS (idx) = TEMPLATE_PARM_DESCENDANTS (orig_idx);
+  TEMPLATE_PARM_PARAMETER_PACK (idx) = TEMPLATE_PARM_PARAMETER_PACK (orig_idx);
+  set_template_parms_num_siblings (idx, num_parms);
+  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, num_parms);
+
+  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)
+    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),
+				     decl, type);
+
+  TEMPLATE_PARM_DESCENDANTS (index) = TEMPLATE_PARM_DESCENDANTS (i);
+  TEMPLATE_PARM_PARAMETER_PACK (index) = TEMPLATE_PARM_PARAMETER_PACK (i);
+  set_template_parms_num_siblings (index, num_parms);
+
+  type = tsubst (type, args, tf_none, NULL_TREE);
+  
+  TREE_TYPE (decl) = type;
+  TREE_TYPE (index) = type;
+
+  return index;
+}
+
+/* Walk current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static void
+fixup_template_parms (void)
+{
+  tree parm;
+  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);
+
+  fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+  /* Let's do the proper fixup now.  */
+  for (i = 0; i < num_parms; ++i)
+    {
+      tree cur = TREE_VEC_ELT (parameter_vec, i);
+
+      /* This is the current template parameter we need to fix up.  */
+      parm = TREE_VALUE (cur);
+
+      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, i) = template_parm_to_arg (cur);
+
+	  if (TREE_PURPOSE (cur))
+	    {
+	      /* So the current template type parameter has a default
+		 argument. Substitute the so far fixed-up template
+		 parms into it.   */
+	      tree default_arg = TREE_PURPOSE (cur);
+
+	      if (TYPE_P (default_arg)
+		  && !dependent_type_p (default_arg))
+		continue;
+
+	      arglist = current_template_args ();
+	      ++cp_unevaluated_operand;
+	      TREE_PURPOSE (cur) =
+		tsubst_expr (default_arg, arglist,
+			     tf_none, default_arg, false);
+	      --cp_unevaluated_operand;
+	    }
+	}
+      else if (TREE_CODE (parm) == TEMPLATE_DECL)
+	{
+	  /* PARM is a template template parameter. This is going to
+	     be interesting.  */
+	  tree tparms, targs, innermost_args;
+	  int j;
+
+	  /* First, fix up the type of the parm.  */
+
+	  tree t =
+	    fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
+	  TREE_TYPE (parm) = t;
+
+	  TREE_VEC_ELT (fixedup_args, i) = template_parm_to_arg (cur);
+
+	  /* Now we need to substitute the template parm types that
+	     have been fixed up so far into the non-type 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.
+
+	     Sot 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 substed_parm, 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);
+
+	      /* Only substitute into template non-type parms.  */
+	      if (parameter != NULL_TREE
+		  && TREE_CODE (parameter) == TREE_LIST
+		  && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
+		      || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
+		continue;
+
+	      if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
+		continue;
+
+	      ++cp_unevaluated_operand;
+	      substed_parm = tsubst_template_parm (parameter, targs, tf_none);
+	      --cp_unevaluated_operand;
+
+	      /* Update the template parameters of PARM.  */
+	      TREE_VEC_ELT (tparms, j) = substed_parm;
+
+	      /* Update the vector of parms we have tsubsted into so
+		 far.  */
+	      TREE_VEC_ELT (innermost_args, j) =
+		template_parm_to_arg (substed_parm);
+	    }
+	}
+      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);
+	  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, i) = template_parm_to_arg (cur);
+	  TREE_TYPE (parm) = tsubst (TREE_TYPE (parm), arglist,
+				     tf_none, NULL_TREE);
+	  TREE_VALUE (cur) = parm;
+	}
+    }
+}
+
 /* end_template_decl is called after a template declaration is seen.  */
 
 void
@@ -3613,6 +3935,65 @@ end_template_decl (void)
   current_template_parms = TREE_CHAIN (current_template_parms);
 }
 
+/* Takes a TREE_LIST representing a template parameter and convert it
+   into an argument suitable to be passed to the type substitution
+   functions.  */
+
+static tree
+template_parm_to_arg (tree t)
+{
+
+  if (t == NULL_TREE
+      || TREE_CODE (t) != TREE_LIST
+      || error_operand_p (TREE_VALUE (t)))
+    return t;
+
+  t = TREE_VALUE (t);
+
+  if (TREE_CODE (t) == TYPE_DECL
+      || TREE_CODE (t) == TEMPLATE_DECL)
+    {
+      t = TREE_TYPE (t);
+
+      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a TYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t = cxx_make_type (TYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	}
+    }
+  else
+    {
+      t = DECL_INITIAL (t);
+
+      if (TEMPLATE_PARM_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a NONTYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+	  tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t  = make_node (NONTYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	  TREE_TYPE (t) = type;
+	}
+    }
+  return t;
+}
+
 /* Within the declaration of a template, return all levels of template
    parameters that apply.  The template parameters are represented as
    a TREE_VEC, in the form documented in cp-tree.h for template
@@ -3639,63 +4020,7 @@ current_template_args (void)
 
       TREE_TYPE (a) = NULL_TREE;
       for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
-	{
-	  tree t = TREE_VEC_ELT (a, i);
-
-	  /* T will be a list if we are called from within a
-	     begin/end_template_parm_list pair, but a vector directly
-	     if within a begin/end_member_template_processing pair.  */
-	  if (TREE_CODE (t) == TREE_LIST)
-	    {
-	      t = TREE_VALUE (t);
-
-	      if (!error_operand_p (t))
-		{
-		  if (TREE_CODE (t) == TYPE_DECL
-		      || TREE_CODE (t) == TEMPLATE_DECL)
-                    {
-                      t = TREE_TYPE (t);
-                      
-                      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a TYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t = cxx_make_type (TYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                        }
-                    }
-                  else
-                    {
-                      t = DECL_INITIAL (t);
-                      
-                      if (TEMPLATE_PARM_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a NONTYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-                          tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t  = make_node (NONTYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                          TREE_TYPE (t) = type;
-                        }
-                    }
-		  TREE_VEC_ELT (a, i) = t;
-                }
-	    }
-	}
+	TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
 
 #ifdef ENABLE_CHECKING
       SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
@@ -3706,7 +4031,23 @@ current_template_args (void)
       else
 	args = a;
     }
-
+  
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.
+      */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -8740,8 +9081,6 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
 	{
           tree tuple;
-          tree default_value;
-          tree parm_decl;
 
           if (parms == error_mark_node)
             continue;
@@ -8751,18 +9090,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
           if (tuple == error_mark_node)
             continue;
 
-          default_value = TREE_PURPOSE (tuple);
-          parm_decl = TREE_VALUE (tuple);
-
-	  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
-	  if (TREE_CODE (parm_decl) == PARM_DECL
-	      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
-	    parm_decl = error_mark_node;
-	  default_value = tsubst_template_arg (default_value, args,
-					       complain, NULL_TREE);
-
-	  tuple = build_tree_list (default_value, parm_decl);
-	  TREE_VEC_ELT (new_vec, i) = tuple;
+	  TREE_VEC_ELT (new_vec, i) =
+	    tsubst_template_parm (tuple, args, complain);
 	}
 
       *new_parms =
@@ -8776,6 +9105,100 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Return the result of substituting ARGS into one template parameter
+   given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+   parameter and which TREE_PURPOSE is the default argument of the
+   template parameter.  */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+  tree default_value, parm_decl;
+
+  if (args == NULL_TREE
+      || t == NULL_TREE
+      || t == error_mark_node)
+    return t;
+
+  gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+  default_value = TREE_PURPOSE (t);
+  parm_decl = TREE_VALUE (t);
+
+  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+  if (TREE_CODE (parm_decl) == PARM_DECL
+      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+    parm_decl = error_mark_node;
+  default_value = tsubst_template_arg (default_value, args,
+				       complain, NULL_TREE);
+
+  return build_tree_list (default_value, parm_decl);
+}
+
+/* Return the size of template of the parameters list T belongs to.  T
+   is either a template parameter type, a template non-type parameter
+   or a template parameter index.  */
+
+int
+get_template_parms_num_siblings (tree t)
+{
+  unsigned result;
+
+  gcc_assert (t != NULL_TREE
+	      && (TREE_CODE (t) == TEMPLATE_PARM_INDEX
+		  || TREE_CODE (t) == TEMPLATE_TYPE_PARM
+		  || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+		  || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM
+		  || (TREE_CODE (t) == PARM_DECL
+		      && DECL_TEMPLATE_PARM_P (t))));
+
+  switch (TREE_CODE (t))
+    {
+    case TEMPLATE_PARM_INDEX:
+      result = TEMPLATE_PARM_NUM_SIBLINGS (t);
+      break;
+    case PARM_DECL:
+      result = get_template_parms_num_siblings (DECL_INITIAL (t));
+      break;
+    default:
+      result =
+	get_template_parms_num_siblings (TEMPLATE_TYPE_PARM_INDEX (t));
+      break;
+    }
+  return result;
+}
+
+/* Set the size of template of the parameters list T belongs to.  T is
+   either a template parameter type, a template non-type parameter or
+   a template parameter index.  */
+
+void
+set_template_parms_num_siblings (tree t, int num_parms)
+{
+  gcc_assert (t != NULL_TREE
+	      && (TREE_CODE (t) == TEMPLATE_PARM_INDEX
+		  || TREE_CODE (t) == TEMPLATE_TYPE_PARM
+		  || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+		  || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM
+		  || (TREE_CODE (t) == PARM_DECL
+		      && DECL_TEMPLATE_PARM_P (t))));
+
+  switch (TREE_CODE (t))
+    {
+    case TEMPLATE_PARM_INDEX:
+      TEMPLATE_PARM_NUM_SIBLINGS (t) = num_parms;
+      break;
+    case PARM_DECL:
+      set_template_parms_num_siblings (DECL_INITIAL (t), num_parms);
+      break;
+    default:
+      set_template_parms_num_siblings (TEMPLATE_TYPE_PARM_INDEX (t),
+				       num_parms);
+      break;
+    }
+}
+
+
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
@@ -10291,7 +10714,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		else if (TYPE_STRUCTURAL_EQUALITY_P (t))
 		  SET_TYPE_STRUCTURAL_EQUALITY (r);
 		else
-		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
+		  {
+		    int num_parms =
+		      get_template_parms_num_siblings (t);
+		    TYPE_CANONICAL (r) =
+		      canonical_type_parameter (r, num_parms);
+		  }
 
 		if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
 		  {
@@ -14701,6 +15129,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  {
 	    tree parmvec = TYPE_TI_ARGS (parm);
 	    tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+	    tree full_argvec = add_to_template_args (targs, argvec);
 	    tree parm_parms 
               = DECL_INNERMOST_TEMPLATE_PARMS
 	          (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14735,7 +15164,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	      the global operator+ will be used; if they are not, the
 	      Lvalue_proxy will be converted to float.  */
 	    if (coerce_template_parms (parm_parms,
-                                       argvec,
+                                       full_argvec,
 				       TYPE_TI_TEMPLATE (parm),
 				       tf_none,
 				       /*require_all_args=*/true,
@@ -17781,7 +18210,8 @@ type_dependent_expression_p (tree expression)
   if (!processing_template_decl)
     return false;
 
-  if (expression == error_mark_node)
+  if (expression == error_mark_node
+      || expression == NULL_TREE)
     return false;
 
   /* An unresolved name is always dependent.  */
@@ -18401,7 +18831,7 @@ make_auto (void)
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
     (0, processing_template_decl + 1, processing_template_decl + 1,
      TYPE_NAME (au), NULL_TREE);
-  TYPE_CANONICAL (au) = canonical_type_parameter (au);
+  TYPE_CANONICAL (au) = canonical_type_parameter (au, 0);
   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 ddfb354..f238f5a 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1062,22 +1062,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index eff6704..13d1ae1 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,114 +1143,20 @@ comp_template_parms_position (tree t1, tree t2)
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
-
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* If T1 and T2 belong to template parm lists of different size,
+     let's assume they are different.  */
+  if (get_template_parms_num_siblings (TYPE_MAIN_VARIANT (t1))
+      != get_template_parms_num_siblings (TYPE_MAIN_VARIANT (t2)))
     return false;
 
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+      || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+      || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
+	  != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1295,12 +1201,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1345,6 +1245,7 @@ structural_comptypes (tree t1, tree t2, int strict)
 	  (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
 	   DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2))))
 	return false;
+
       if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
 	break;
       /* Don't check inheritance.  */
@@ -1401,8 +1302,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* If T1 and T2 don't have the same relative position in their
+	 template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+	return false;
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..f6155c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+#include <list>
+
+template<class T>
+class Test
+{
+protected:
+  typedef std::list<T> ListAlias;
+  ListAlias list;
+public:
+  typedef typename ListAlias::const_iterator const_iterator;
+  inline const_iterator begin() const;
+
+};
+
+template<class T>
+inline typename std::list<T>::const_iterator Test<T>::begin() const
+{
+  return list.begin();
+}
+

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-06 18:53                               ` Dodji Seketeli
@ 2010-10-06 22:15                                 ` Paolo Carlini
  2010-10-15 16:09                                   ` Dodji Seketeli
  2010-10-07 18:30                                 ` Jason Merrill
  1 sibling, 1 reply; 38+ messages in thread
From: Paolo Carlini @ 2010-10-06 22:15 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Jason Merrill, H.J. Lu, GCC Patches

Hi,

> diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
> new file mode 100644
> index 0000000..f6155c1
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/typedef36.C
> @@ -0,0 +1,23 @@
> +// Origin: PR c++/45606
> +// { dg-do compile }
> +
> +#include <list>
> +
> +template<class T>
> +class Test
> +{
> +protected:
> +  typedef std::list<T> ListAlias;
> +  ListAlias list;
> +public:
> +  typedef typename ListAlias::const_iterator const_iterator;
> +  inline const_iterator begin() const;
> +
> +};
> +
> +template<class T>
> +inline typename std::list<T>::const_iterator Test<T>::begin() const
> +{
> +  return list.begin();
> +}
> +

Once again, if, thanks to the analysis you did to fix the problem, you are able to quickly figure out a shorter testcase, not including the entire <list>, I think it would be good.

Thanks,
Paolo

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-06 18:53                               ` Dodji Seketeli
  2010-10-06 22:15                                 ` Paolo Carlini
@ 2010-10-07 18:30                                 ` Jason Merrill
  1 sibling, 0 replies; 38+ messages in thread
From: Jason Merrill @ 2010-10-07 18:30 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: H.J. Lu, Paolo Carlini, GCC Patches

This is shaping up well, but there are still some issues:

On 10/06/2010 02:52 PM, Dodji Seketeli wrote:
> -/* Contains canonical template parameter types. The vector is indexed by
> -   the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
> -   TREE_LIST, whose TREE_VALUEs contain the canonical template
> -   parameters of various types and levels.  */
> +/* Contains canonical template parameter types. The vector is indexed
> +   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
> +   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
> +   total size of the template parameter list a given template
> +   parameter would belong too, and whose TREE_VALUEs contain the
> +   canonical template parameters of various types and levels,
> +   belonging to a set of template parameters which size is
> +   TREE_PURPOSE.  */

We don't really need to change the representation this way, do we?  We 
can just let structural_comptypes verify that the total parms # matches. 
  Same with the changes to canonical_type_parameter.

> +         if (TREE_PURPOSE (cur))
> +           {
> +             /* So the current template type parameter has a default
> +                argument. Substitute the so far fixed-up template
> +                parms into it.   */
> +             tree default_arg = TREE_PURPOSE (cur);
> +
> +             if (TYPE_P (default_arg)
> +                 && !dependent_type_p (default_arg))
> +               continue;
> +
> +             arglist = current_template_args ();

Why do we need to get current_template_args() again here?

> +             ++cp_unevaluated_operand;
> +             TREE_PURPOSE (cur) =
> +               tsubst_expr (default_arg, arglist,
> +                            tf_none, default_arg, false);
> +             --cp_unevaluated_operand;

tsubst (default_arg, arglist, tf_warning_or_error, parm);

And don't mess with cp_unevaluated_operand.

> +         /* Now we need to substitute the template parm types that
> +            have been fixed up so far into the non-type template
> +            parms of this template template parm. E.g, consider this:

This needs to be recursive, in case the template template parm has its 
own template template parms.

template <class T, template <template <class U = T> class V> class W> 
class A;

> +             ++cp_unevaluated_operand;
> +             substed_parm = tsubst_template_parm (parameter, targs, tf_none);
> +             --cp_unevaluated_operand;

Still shouldn't be messing with cp_unevaluated_operand.  And we should 
use tf_warning_or_error.

Also, don't we need to handle default template template arguments?

template <template <class T> class A, template <class T> class B = A> 
class C;

> +         /* 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, i) = template_parm_to_arg (cur);
> +         TREE_TYPE (parm) = tsubst (TREE_TYPE (parm), arglist,
> +                                    tf_none, NULL_TREE);

Don't we need to set the type of pushed_decl, too?

> +         TREE_VALUE (cur) = parm;

But we don't need to set this, as parm hasn't changed.

> +extern void set_template_parms_num_siblings     (tree, int);

I don't think we want this function.  Instead, add a siblings parm to 
build_template_parm_index.

> @@ -17789,7 +18218,8 @@ type_dependent_expression_p (tree expression)
>    if (!processing_template_decl)
>      return false;
>
> -  if (expression == error_mark_node)
> +  if (expression == error_mark_node
> +      || expression == NULL_TREE)

What made this necessary?  I would think this should be caught in the 
caller.

> +  /* If T1 and T2 belong to template parm lists of different size,
> +     let's assume they are different.  */
> +  if (get_template_parms_num_siblings (TYPE_MAIN_VARIANT (t1))
> +      != get_template_parms_num_siblings (TYPE_MAIN_VARIANT (t2)))
>      return false;

> +  /* Then compare their relative position.  */
> +  if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
> +      || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
> +      || (TEMPLATE_TYPE_PARAMETER_PACK (t1)
> +         != TEMPLATE_TYPE_PARAMETER_PACK (t2)))

All of these are looking at the TEMPLATE_PARM_INDEX, so we might as well 
pull it out and operate on it directly with TEMPLATE_PARM_*.

You need more testcases.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-06 22:15                                 ` Paolo Carlini
@ 2010-10-15 16:09                                   ` Dodji Seketeli
  2010-10-20 15:43                                     ` Jason Merrill
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-10-15 16:09 UTC (permalink / raw)
  To: Paolo Carlini; +Cc: Jason Merrill, H.J. Lu, GCC Patches


Hello Paolo, Jason,

I am replying to both of your messages in below.

Paolo Carlini <pcarlini@gmail.com> writes:

[...]

>> diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
>> new file mode 100644
>> index 0000000..f6155c1
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.dg/template/typedef36.C
>> @@ -0,0 +1,23 @@
>> +// Origin: PR c++/45606
>> +// { dg-do compile }
>> +
>> +#include <list>

[...]

>
> Once again, if, thanks to the analysis you did to fix the problem, you
> are able to quickly figure out a shorter testcase, not including the
> entire <list>, I think it would be good.

You are right. Sorry for not having done it before. It is now done in
the udpated patch below.


Jason Merrill <jason@redhat.com> writes:

[...]

>> -/* Contains canonical template parameter types. The vector is indexed by
>> -   the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
>> -   TREE_LIST, whose TREE_VALUEs contain the canonical template
>> -   parameters of various types and levels.  */
>> +/* Contains canonical template parameter types. The vector is indexed
>> +   by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
>> +   a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
>> +   total size of the template parameter list a given template
>> +   parameter would belong too, and whose TREE_VALUEs contain the
>> +   canonical template parameters of various types and levels,
>> +   belonging to a set of template parameters which size is
>> +   TREE_PURPOSE.  */
>
> We don't really need to change the representation this way, do we?  We
> can just let structural_comptypes verify that the total parms #
> matches. Same with the changes to canonical_type_parameter.

Done.

>
>> +         if (TREE_PURPOSE (cur))
>> +           {
>> +             /* So the current template type parameter has a default
>> +                argument. Substitute the so far fixed-up template
>> +                parms into it.   */
>> +             tree default_arg = TREE_PURPOSE (cur);
>> +
>> +             if (TYPE_P (default_arg)
>> +                 && !dependent_type_p (default_arg))
>> +               continue;
>> +
>> +             arglist = current_template_args ();
>
> Why do we need to get current_template_args() again here?
>

I wonder why myself. Thanks for catching this. I removed it.

>> +             ++cp_unevaluated_operand;
>> +             TREE_PURPOSE (cur) =
>> +               tsubst_expr (default_arg, arglist,
>> +                            tf_none, default_arg, false);
>> +             --cp_unevaluated_operand;
>
> tsubst (default_arg, arglist, tf_warning_or_error, parm);
>
> And don't mess with cp_unevaluated_operand.
>

Done.

>> +         /* Now we need to substitute the template parm types that
>> +            have been fixed up so far into the non-type template
>> +            parms of this template template parm. E.g, consider this:
>
> This needs to be recursive, in case the template template parm has its
> own template template parms.
>
> template <class T, template <template <class U = T> class V> class W>
> class A;

Oops, done now.

>> +             ++cp_unevaluated_operand;
>> +             substed_parm = tsubst_template_parm (parameter, targs, tf_none);
>> +             --cp_unevaluated_operand;
>
> Still shouldn't be messing with cp_unevaluated_operand.  And we should
> use tf_warning_or_error.

Done.

>
> Also, don't we need to handle default template template arguments?
>

I am not sure about this but can a default template template argument
depend on the template parms of the current template being declared?
e.g, in:

template<class T>
struct C
{
};

template<class U,
	 template<class V> class W = C>
struct S
{
};

Here, the template parms of C haven't been created in the template parm
list of S. Furthermore, couldn't tsubsting U into C would wrongly
remplace the template parm T of C with U? I said wrongly because now
with this patch T and U are different types.

> template <template <class T> class A, template <class T> class B = A>
> class C;
>
>> +         /* 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, i) = template_parm_to_arg (cur);
>> +         TREE_TYPE (parm) = tsubst (TREE_TYPE (parm), arglist,
>> +                                    tf_none, NULL_TREE);
>
> Don't we need to set the type of pushed_decl, too?

Ah, it is done by the call to fixup_template_parm_index right before the
snippet of code you quoted. as that function takes care of updating all
references to template type parms from the index. I have added a comment
for that.

>
>> +         TREE_VALUE (cur) = parm;
>
> But we don't need to set this, as parm hasn't changed.
>

Sigh. True. Removed.

>> +extern void set_template_parms_num_siblings     (tree, int);
>
> I don't think we want this function.  Instead, add a siblings parm to
> build_template_parm_index.
>

Done.

>> @@ -17789,7 +18218,8 @@ type_dependent_expression_p (tree expression)
>>    if (!processing_template_decl)
>>      return false;
>>
>> -  if (expression == error_mark_node)
>> +  if (expression == error_mark_node
>> +      || expression == NULL_TREE)
>
> What made this necessary?  I would think this should be caught in the
> caller.

This is actually not necessary. I think I tentatively added this while
looking for why I was breaking so many regression tests at some point
and forgot to remove it. I have removed it from the patch.

>
>> +  /* If T1 and T2 belong to template parm lists of different size,
>> +     let's assume they are different.  */
>> +  if (get_template_parms_num_siblings (TYPE_MAIN_VARIANT (t1))
>> +      != get_template_parms_num_siblings (TYPE_MAIN_VARIANT (t2)))
>>      return false;
>
>> +  /* Then compare their relative position.  */
>> +  if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
>> +      || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
>> +      || (TEMPLATE_TYPE_PARAMETER_PACK (t1)
>> +         != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
>
> All of these are looking at the TEMPLATE_PARM_INDEX, so we might as
> well pull it out and operate on it directly with TEMPLATE_PARM_*.
>

Done. With this change we don't need get_template_parms_num_siblings
anymore either so I have removed it too.

> You need more testcases.

I have added some more.

I fully bootstrapped and tested the patch on x86_64-unknown-linux-gnu.

Thanks.

-- 
	Dodji

commit f9f41f7aa304f644ba52f660ab680376a97ce61c
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for dependent typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
    	(struct template_parm_index_s)<num_siblings>: New field.
    	(TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
    	(fixup_template_parm, fixup_template_parms): New private
    	functions.
    	(current_template_args): Declare this.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(build_template_parm_index): Add a new argument to carry the total
    	number of template parms.
    	(reduce_template_parm_level, process_template_parm, make_auto): Adjust.
    	(current_template_args): Fix this for template template
    	parameters.
    	(tsubst_template_parm): Split out of ...
    	(tsubst_template_parms): ... this.
    	(reduce_template_parm_level): Don't loose
    	TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
    	(template_parm_to_arg): Extracted this function ...
    	(current_template_args): ... from this one.
    	(end_template_parm_list): Do not update template sibling parms
    	here anymore. Use fixup_template_parms instead.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
    	using all the arguments deduced so far.
    	(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
    	canonical_type_parameter.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore.
    	(comp_template_parms_position): Re-organized. Take the length of
    	template parms list in account.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* g++.dg/template/typedef36.C: New test.
    	* gcc/testsuite/g++.dg/template/canon-type-9.C: New test.
    	* g++.dg/template/canon-type-10.C: New test.
    	* g++.dg/template/canon-type-11.C: New test.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f76c2be..d03b5b1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6690,7 +6690,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 626e452..1c009e5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -236,6 +236,7 @@ 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;
@@ -4306,6 +4307,9 @@ 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)
@@ -4327,10 +4331,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5012,7 +5012,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5348,7 +5348,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index fcc83fb..3ba2a28 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8b2e542..0a93da8 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3e02cd5..3d4444b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11018,6 +11018,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms.  We first need to know
+     the total number of template parms to be able to compute proper
+     canonical types of each dependent type. So after the loop, when
+     we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11036,11 +11043,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a365603..7737ccc 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -137,7 +137,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, tree, tree);
+static tree build_template_parm_index (int, 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);
@@ -190,6 +190,12 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree template_parm_to_arg (tree t);
+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 void fixup_template_parms (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3346,12 +3352,14 @@ check_template_shadow (tree decl)
 }
 
 /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
-   ORIG_LEVEL, DECL, and TYPE.  */
+   ORIG_LEVEL, DECL, and TYPE.  NUM_SIBLINGS is the total number of
+   template parameters.  */
 
 static tree
 build_template_parm_index (int index,
 			   int level,
 			   int orig_level,
+			   int num_siblings,
 			   tree decl,
 			   tree type)
 {
@@ -3359,6 +3367,7 @@ 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);
@@ -3370,6 +3379,7 @@ build_template_parm_index (int index,
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
    if no such parameter existed.  */
+
 static tree
 canonical_type_parameter (tree type)
 {
@@ -3423,6 +3433,7 @@ 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) 
@@ -3438,15 +3449,20 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter shall
+   be set to 0.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3521,6 +3537,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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)) 
@@ -3554,6 +3571,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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);
@@ -3586,16 +3604,323 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
-	      current_template_parms;
     }
 
+  fixup_template_parms ();
+
   --processing_template_parmlist;
 
   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 = copy_type (type);
+  /* 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 = 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)
+    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. 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);
+
+  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);
+
+      if (TREE_PURPOSE (parm_desc))
+	{
+	  /* So the current template type parameter has a default
+	     argument. Substitute the so far fixed-up template
+	     parms into it.   */
+	  tree default_arg = TREE_PURPOSE (parm_desc);
+
+	  if (TYPE_P (default_arg)
+	      && !dependent_type_p (default_arg))
+	    return;
+
+	  TREE_PURPOSE (parm_desc) =
+	    tsubst (default_arg, arglist,
+		    tf_warning_or_error, parm);
+	}
+    }
+  else if (TREE_CODE (parm) == TEMPLATE_DECL)
+    {
+      /* PARM is a template template parameter. This is going to
+	 be interesting.  */
+      tree tparms, targs, innermost_args;
+      int j;
+
+      /* First, fix up the type of the parm.  */
+
+      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);
+
+      /* Now we need to substitute the template parm types that
+	 have been fixed up so far into the non-type 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.
+
+	 Sot 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);
+
+	  /* Only substitute into template non-type parms.  */
+	  if (parameter != NULL_TREE
+	      && TREE_CODE (parameter) == TREE_LIST
+	      && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
+		  || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
+	    continue;
+
+	  if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
+	    continue;
+
+	  fixup_template_parm (parameter, j,
+			       TREE_VEC_LENGTH (tparms),
+			       targs);
+	}
+    }
+  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_warning_or_error, NULL_TREE);
+    }
+}
+
+/* Walk current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static 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);
+
+  fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+  /* 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
@@ -3613,6 +3938,65 @@ end_template_decl (void)
   current_template_parms = TREE_CHAIN (current_template_parms);
 }
 
+/* Takes a TREE_LIST representing a template parameter and convert it
+   into an argument suitable to be passed to the type substitution
+   functions.  */
+
+static tree
+template_parm_to_arg (tree t)
+{
+
+  if (t == NULL_TREE
+      || TREE_CODE (t) != TREE_LIST
+      || error_operand_p (TREE_VALUE (t)))
+    return t;
+
+  t = TREE_VALUE (t);
+
+  if (TREE_CODE (t) == TYPE_DECL
+      || TREE_CODE (t) == TEMPLATE_DECL)
+    {
+      t = TREE_TYPE (t);
+
+      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a TYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t = cxx_make_type (TYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	}
+    }
+  else
+    {
+      t = DECL_INITIAL (t);
+
+      if (TEMPLATE_PARM_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a NONTYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+	  tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t  = make_node (NONTYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	  TREE_TYPE (t) = type;
+	}
+    }
+  return t;
+}
+
 /* Within the declaration of a template, return all levels of template
    parameters that apply.  The template parameters are represented as
    a TREE_VEC, in the form documented in cp-tree.h for template
@@ -3639,63 +4023,7 @@ current_template_args (void)
 
       TREE_TYPE (a) = NULL_TREE;
       for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
-	{
-	  tree t = TREE_VEC_ELT (a, i);
-
-	  /* T will be a list if we are called from within a
-	     begin/end_template_parm_list pair, but a vector directly
-	     if within a begin/end_member_template_processing pair.  */
-	  if (TREE_CODE (t) == TREE_LIST)
-	    {
-	      t = TREE_VALUE (t);
-
-	      if (!error_operand_p (t))
-		{
-		  if (TREE_CODE (t) == TYPE_DECL
-		      || TREE_CODE (t) == TEMPLATE_DECL)
-                    {
-                      t = TREE_TYPE (t);
-                      
-                      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a TYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t = cxx_make_type (TYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                        }
-                    }
-                  else
-                    {
-                      t = DECL_INITIAL (t);
-                      
-                      if (TEMPLATE_PARM_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a NONTYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-                          tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t  = make_node (NONTYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                          TREE_TYPE (t) = type;
-                        }
-                    }
-		  TREE_VEC_ELT (a, i) = t;
-                }
-	    }
-	}
+	TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
 
 #ifdef ENABLE_CHECKING
       SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
@@ -3707,6 +4035,22 @@ current_template_args (void)
 	args = a;
     }
 
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.
+      */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -8741,8 +9085,6 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
 	{
           tree tuple;
-          tree default_value;
-          tree parm_decl;
 
           if (parms == error_mark_node)
             continue;
@@ -8752,18 +9094,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
           if (tuple == error_mark_node)
             continue;
 
-          default_value = TREE_PURPOSE (tuple);
-          parm_decl = TREE_VALUE (tuple);
-
-	  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
-	  if (TREE_CODE (parm_decl) == PARM_DECL
-	      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
-	    parm_decl = error_mark_node;
-	  default_value = tsubst_template_arg (default_value, args,
-					       complain, NULL_TREE);
-
-	  tuple = build_tree_list (default_value, parm_decl);
-	  TREE_VEC_ELT (new_vec, i) = tuple;
+	  TREE_VEC_ELT (new_vec, i) =
+	    tsubst_template_parm (tuple, args, complain);
 	}
 
       *new_parms =
@@ -8777,6 +9109,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Return the result of substituting ARGS into one template parameter
+   given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+   parameter and which TREE_PURPOSE is the default argument of the
+   template parameter.  */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+  tree default_value, parm_decl;
+
+  if (args == NULL_TREE
+      || t == NULL_TREE
+      || t == error_mark_node)
+    return t;
+
+  gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+  default_value = TREE_PURPOSE (t);
+  parm_decl = TREE_VALUE (t);
+
+  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+  if (TREE_CODE (parm_decl) == PARM_DECL
+      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+    parm_decl = error_mark_node;
+  default_value = tsubst_template_arg (default_value, args,
+				       complain, NULL_TREE);
+
+  return build_tree_list (default_value, parm_decl);
+}
+
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
@@ -14717,6 +15079,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  {
 	    tree parmvec = TYPE_TI_ARGS (parm);
 	    tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+	    tree full_argvec = add_to_template_args (targs, argvec);
 	    tree parm_parms 
               = DECL_INNERMOST_TEMPLATE_PARMS
 	          (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14751,7 +15114,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	      the global operator+ will be used; if they are not, the
 	      Lvalue_proxy will be converted to float.  */
 	    if (coerce_template_parms (parm_parms,
-                                       argvec,
+                                       full_argvec,
 				       TYPE_TI_TEMPLATE (parm),
 				       tf_none,
 				       /*require_all_args=*/true,
@@ -18425,7 +18788,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,
-     TYPE_NAME (au), NULL_TREE);
+     0, 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 93d13a1..a1ed527 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1062,22 +1062,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index ca832c6..cb6ee57 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
 static bool
 comp_template_parms_position (tree t1, tree t2)
 {
+  tree index1, index2;
   gcc_assert (t1 && t2
 	      && TREE_CODE (t1) == TREE_CODE (t2)
 	      && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
+  index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
+  index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
 
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* 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;
 
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
+      || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
+      || (TEMPLATE_PARM_PARAMETER_PACK (index1)
+	  != TEMPLATE_PARM_PARAMETER_PACK (index2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1301,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1407,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* If T1 and T2 don't have the same relative position in their
+	 template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+	return false;
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/canon-type-10.C b/gcc/testsuite/g++.dg/template/canon-type-10.C
new file mode 100644
index 0000000..0c38946
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-10.C
@@ -0,0 +1,23 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U = TT<int, C> >
+struct S
+{
+  void foo(TT<T, C>);
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U>
+void
+S<T, TT, U>::foo(TT<T, C>)
+{
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-11.C b/gcc/testsuite/g++.dg/template/canon-type-11.C
new file mode 100644
index 0000000..698fe31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-11.C
@@ -0,0 +1,39 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+  void bar();
+};
+
+template<class T>
+void
+C<T>::bar()
+{
+}
+
+
+template<class U,
+	 template<class TT0_T0> class TT0 = C,
+	 template<class TT1_T0> class TT1 = TT0>
+struct S
+{
+  C<U> s;
+
+  void foo(TT1<U>);
+
+  void bar()
+  {
+    foo(s);
+  }
+};
+
+template<class T,
+	 template<class TT0_T0> class TT0,
+	 template<class TT1_T0> class TT1>
+void
+S<T, TT0, TT1>::foo(TT1<T>)
+{
+  C<T> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-9.C b/gcc/testsuite/g++.dg/template/canon-type-9.C
new file mode 100644
index 0000000..de6170e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-9.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-options "-std=c++0x" }
+// { dg-do "compile" }
+
+struct F { F(int) {}};
+
+template<class T, T* u>
+struct S
+{
+  decltype(u) foo(T);
+};
+
+template<class T, T *u>
+T* S<T, u>::foo(T)
+{
+  T t;
+  return t;
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..318deef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+template<class T, class U = int>
+struct S0
+{
+  typedef int const_iterator;
+};
+
+template<class T>
+struct Test
+{
+  typedef S0<T> SAlias;
+  typedef typename SAlias::const_iterator const_iterator;
+  const_iterator begin ();
+};
+
+template<class T>
+typename S0<T>::const_iterator
+Test<T>::begin()
+{
+  return 0;
+}

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-15 16:09                                   ` Dodji Seketeli
@ 2010-10-20 15:43                                     ` Jason Merrill
  2010-10-20 21:10                                       ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Jason Merrill @ 2010-10-20 15:43 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, H.J. Lu, GCC Patches

On 10/15/2010 11:44 AM, Dodji Seketeli wrote:
>> Also, don't we need to handle default template template arguments?
>
> I am not sure about this but can a default template template argument
> depend on the template parms of the current template being declared?

Well, yes, as in the example I gave with that question:

>> template<template<class T>  class A, template<class T>  class B = A>
>> class C;

> template<class T>
> struct C
> {
> };
>
> template<class U,
> 	 template<class V>  class W = C>
> struct S
> {
> };
>
> Here, the template parms of C haven't been created in the template parm
> list of S. Furthermore, couldn't tsubsting U into C would wrongly
> remplace the template parm T of C with U? I said wrongly because now
> with this patch T and U are different types.

Right, we don't want to modify C.  Doesn't tsubst_template_arg do the 
right thing?  It looks to me like it ends up calling tsubst_copy, which 
should return C unchanged.

Actually, I guess you can use tsubst_template_arg for all three 
varieties of template parameter, rather than handle each one specifically.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-20 15:43                                     ` Jason Merrill
@ 2010-10-20 21:10                                       ` Dodji Seketeli
  2010-10-20 21:21                                         ` Jason Merrill
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-10-20 21:10 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, H.J. Lu, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 10/15/2010 11:44 AM, Dodji Seketeli wrote:

[...]

>> I am not sure about this but can a default template template argument
>> depend on the template parms of the current template being declared?
>
> Well, yes, as in the example I gave with that question:
>
>>> template<template<class T>  class A, template<class T>  class B = A>
>>> class C;

Oops, right.

>
>> template<class T>
>> struct C
>> {
>> };
>>
>> template<class U,
>> 	 template<class V>  class W = C>
>> struct S
>> {
>> };
>>
>> Here, the template parms of C haven't been created in the template parm
>> list of S. Furthermore, couldn't tsubsting U into C would wrongly
>> remplace the template parm T of C with U? I said wrongly because now
>> with this patch T and U are different types.
>
> Right, we don't want to modify C.  Doesn't tsubst_template_arg do the
> right thing?  It looks to me like it ends up calling tsubst_copy,
> which should return C unchanged.
>
> Actually, I guess you can use tsubst_template_arg for all three
> varieties of template parameter, rather than handle each one
> specifically.

True. I did that in the patch below and it passes c++/libstdc++ tests. I
have also added a couple of tests.

I am currently running a full bootstrap.

-- 
	Dodji

commit 5d4846e03f2cf7d2081e0267cd3437ae214ca707
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for dependent typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
    	(struct template_parm_index_s)<num_siblings>: New field.
    	(TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
    	(fixup_template_parm, fixup_template_parms): New private
    	functions.
    	(current_template_args): Declare this.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(build_template_parm_index): Add a new argument to carry the total
    	number of template parms.
    	(reduce_template_parm_level, process_template_parm, make_auto): Adjust.
    	(current_template_args): Fix this for template template
    	parameters.
    	(tsubst_template_parm): Split out of ...
    	(tsubst_template_parms): ... this.
    	(reduce_template_parm_level): Don't loose
    	TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
    	(template_parm_to_arg): Extracted this function ...
    	(current_template_args): ... from this one.
    	(end_template_parm_list): Do not update template sibling parms
    	here anymore. Use fixup_template_parms instead.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
    	using all the arguments deduced so far.
    	(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
    	canonical_type_parameter.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore.
    	(comp_template_parms_position): Re-organized. Take the length of
    	template parms list in account.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* g++.dg/template/typedef36.C: New test.
    	* gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
    	* g++.dg/template/canon-type-10.C: Likewise.
    	* g++.dg/template/canon-type-11.C: Likewise.
    	* g++.dg/template/canon-type-12.C: Likewise.
    	* g++.dg/template/canon-type-13.C: Likewise.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f76c2be..d03b5b1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6690,7 +6690,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 626e452..1c009e5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -236,6 +236,7 @@ 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;
@@ -4306,6 +4307,9 @@ 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)
@@ -4327,10 +4331,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5012,7 +5012,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5348,7 +5348,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index fcc83fb..3ba2a28 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8b2e542..0a93da8 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3e02cd5..3d4444b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11018,6 +11018,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms.  We first need to know
+     the total number of template parms to be able to compute proper
+     canonical types of each dependent type. So after the loop, when
+     we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11036,11 +11043,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a365603..522efbd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -137,7 +137,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, tree, tree);
+static tree build_template_parm_index (int, 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);
@@ -190,6 +190,12 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree template_parm_to_arg (tree t);
+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 void fixup_template_parms (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3346,12 +3352,14 @@ check_template_shadow (tree decl)
 }
 
 /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
-   ORIG_LEVEL, DECL, and TYPE.  */
+   ORIG_LEVEL, DECL, and TYPE.  NUM_SIBLINGS is the total number of
+   template parameters.  */
 
 static tree
 build_template_parm_index (int index,
 			   int level,
 			   int orig_level,
+			   int num_siblings,
 			   tree decl,
 			   tree type)
 {
@@ -3359,6 +3367,7 @@ 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);
@@ -3370,6 +3379,7 @@ build_template_parm_index (int index,
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
    if no such parameter existed.  */
+
 static tree
 canonical_type_parameter (tree type)
 {
@@ -3423,6 +3433,7 @@ 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) 
@@ -3438,15 +3449,20 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter shall
+   be set to 0.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3521,6 +3537,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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)) 
@@ -3554,6 +3571,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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);
@@ -3586,16 +3604,313 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
-	      current_template_parms;
     }
 
+  fixup_template_parms ();
+
   --processing_template_parmlist;
 
   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 = copy_type (type);
+  /* 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 = 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)
+    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. 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);
+
+  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;
+      int j;
+
+      /* First, fix up the type of the parm.  */
+
+      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);
+
+      /* Now we need to substitute the template parm types that
+	 have been fixed up so far into the non-type 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.
+
+	 Sot 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);
+
+	  /* Only substitute into template non-type parms.  */
+	  if (parameter != NULL_TREE
+	      && TREE_CODE (parameter) == TREE_LIST
+	      && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
+		  || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
+	    continue;
+
+	  if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
+	    continue;
+
+	  fixup_template_parm (parameter, j,
+			       TREE_VEC_LENGTH (tparms),
+			       targs);
+	}
+    }
+  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_warning_or_error, NULL_TREE);
+    }
+
+  if (TREE_PURPOSE (parm_desc)
+      && dependent_type_p (TREE_TYPE (TREE_PURPOSE (parm_desc))))
+    TREE_PURPOSE (parm_desc) =
+      tsubst_template_arg (TREE_PURPOSE (parm_desc), arglist,
+			   tf_warning_or_error, parm);
+}
+
+/* Walk current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static 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);
+
+  fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+  /* 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
@@ -3613,6 +3928,65 @@ end_template_decl (void)
   current_template_parms = TREE_CHAIN (current_template_parms);
 }
 
+/* Takes a TREE_LIST representing a template parameter and convert it
+   into an argument suitable to be passed to the type substitution
+   functions.  */
+
+static tree
+template_parm_to_arg (tree t)
+{
+
+  if (t == NULL_TREE
+      || TREE_CODE (t) != TREE_LIST
+      || error_operand_p (TREE_VALUE (t)))
+    return t;
+
+  t = TREE_VALUE (t);
+
+  if (TREE_CODE (t) == TYPE_DECL
+      || TREE_CODE (t) == TEMPLATE_DECL)
+    {
+      t = TREE_TYPE (t);
+
+      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a TYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t = cxx_make_type (TYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	}
+    }
+  else
+    {
+      t = DECL_INITIAL (t);
+
+      if (TEMPLATE_PARM_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a NONTYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+	  tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t  = make_node (NONTYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	  TREE_TYPE (t) = type;
+	}
+    }
+  return t;
+}
+
 /* Within the declaration of a template, return all levels of template
    parameters that apply.  The template parameters are represented as
    a TREE_VEC, in the form documented in cp-tree.h for template
@@ -3639,63 +4013,7 @@ current_template_args (void)
 
       TREE_TYPE (a) = NULL_TREE;
       for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
-	{
-	  tree t = TREE_VEC_ELT (a, i);
-
-	  /* T will be a list if we are called from within a
-	     begin/end_template_parm_list pair, but a vector directly
-	     if within a begin/end_member_template_processing pair.  */
-	  if (TREE_CODE (t) == TREE_LIST)
-	    {
-	      t = TREE_VALUE (t);
-
-	      if (!error_operand_p (t))
-		{
-		  if (TREE_CODE (t) == TYPE_DECL
-		      || TREE_CODE (t) == TEMPLATE_DECL)
-                    {
-                      t = TREE_TYPE (t);
-                      
-                      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a TYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t = cxx_make_type (TYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                        }
-                    }
-                  else
-                    {
-                      t = DECL_INITIAL (t);
-                      
-                      if (TEMPLATE_PARM_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a NONTYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-                          tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t  = make_node (NONTYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                          TREE_TYPE (t) = type;
-                        }
-                    }
-		  TREE_VEC_ELT (a, i) = t;
-                }
-	    }
-	}
+	TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
 
 #ifdef ENABLE_CHECKING
       SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
@@ -3707,6 +4025,22 @@ current_template_args (void)
 	args = a;
     }
 
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.
+      */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -8741,8 +9075,6 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
 	{
           tree tuple;
-          tree default_value;
-          tree parm_decl;
 
           if (parms == error_mark_node)
             continue;
@@ -8752,18 +9084,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
           if (tuple == error_mark_node)
             continue;
 
-          default_value = TREE_PURPOSE (tuple);
-          parm_decl = TREE_VALUE (tuple);
-
-	  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
-	  if (TREE_CODE (parm_decl) == PARM_DECL
-	      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
-	    parm_decl = error_mark_node;
-	  default_value = tsubst_template_arg (default_value, args,
-					       complain, NULL_TREE);
-
-	  tuple = build_tree_list (default_value, parm_decl);
-	  TREE_VEC_ELT (new_vec, i) = tuple;
+	  TREE_VEC_ELT (new_vec, i) =
+	    tsubst_template_parm (tuple, args, complain);
 	}
 
       *new_parms =
@@ -8777,6 +9099,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Return the result of substituting ARGS into one template parameter
+   given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+   parameter and which TREE_PURPOSE is the default argument of the
+   template parameter.  */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+  tree default_value, parm_decl;
+
+  if (args == NULL_TREE
+      || t == NULL_TREE
+      || t == error_mark_node)
+    return t;
+
+  gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+  default_value = TREE_PURPOSE (t);
+  parm_decl = TREE_VALUE (t);
+
+  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+  if (TREE_CODE (parm_decl) == PARM_DECL
+      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+    parm_decl = error_mark_node;
+  default_value = tsubst_template_arg (default_value, args,
+				       complain, NULL_TREE);
+
+  return build_tree_list (default_value, parm_decl);
+}
+
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
@@ -14717,6 +15069,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  {
 	    tree parmvec = TYPE_TI_ARGS (parm);
 	    tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+	    tree full_argvec = add_to_template_args (targs, argvec);
 	    tree parm_parms 
               = DECL_INNERMOST_TEMPLATE_PARMS
 	          (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14751,7 +15104,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	      the global operator+ will be used; if they are not, the
 	      Lvalue_proxy will be converted to float.  */
 	    if (coerce_template_parms (parm_parms,
-                                       argvec,
+                                       full_argvec,
 				       TYPE_TI_TEMPLATE (parm),
 				       tf_none,
 				       /*require_all_args=*/true,
@@ -18425,7 +18778,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,
-     TYPE_NAME (au), NULL_TREE);
+     0, 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 93d13a1..a1ed527 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1062,22 +1062,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index ca832c6..cb6ee57 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
 static bool
 comp_template_parms_position (tree t1, tree t2)
 {
+  tree index1, index2;
   gcc_assert (t1 && t2
 	      && TREE_CODE (t1) == TREE_CODE (t2)
 	      && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
+  index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
+  index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
 
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* 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;
 
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
+      || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
+      || (TEMPLATE_PARM_PARAMETER_PACK (index1)
+	  != TEMPLATE_PARM_PARAMETER_PACK (index2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1301,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1407,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* If T1 and T2 don't have the same relative position in their
+	 template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+	return false;
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/canon-type-10.C b/gcc/testsuite/g++.dg/template/canon-type-10.C
new file mode 100644
index 0000000..0c38946
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-10.C
@@ -0,0 +1,23 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U = TT<int, C> >
+struct S
+{
+  void foo(TT<T, C>);
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U>
+void
+S<T, TT, U>::foo(TT<T, C>)
+{
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-11.C b/gcc/testsuite/g++.dg/template/canon-type-11.C
new file mode 100644
index 0000000..698fe31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-11.C
@@ -0,0 +1,39 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+  void bar();
+};
+
+template<class T>
+void
+C<T>::bar()
+{
+}
+
+
+template<class U,
+	 template<class TT0_T0> class TT0 = C,
+	 template<class TT1_T0> class TT1 = TT0>
+struct S
+{
+  C<U> s;
+
+  void foo(TT1<U>);
+
+  void bar()
+  {
+    foo(s);
+  }
+};
+
+template<class T,
+	 template<class TT0_T0> class TT0,
+	 template<class TT1_T0> class TT1>
+void
+S<T, TT0, TT1>::foo(TT1<T>)
+{
+  C<T> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-12.C b/gcc/testsuite/g++.dg/template/canon-type-12.C
new file mode 100644
index 0000000..694cc5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-12.C
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+
+template<class T, T t = (T)0>
+struct S
+{
+  void
+  foo(decltype(t) = t);
+};
+
+template<class T, T t>
+void
+S<T, t>::foo(T)
+{
+}
+
+void
+bar()
+{
+  S<int> s;
+  s.foo();
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-13.C b/gcc/testsuite/g++.dg/template/canon-type-13.C
new file mode 100644
index 0000000..ca39cea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-13.C
@@ -0,0 +1,27 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct S0
+{
+};
+
+template<class T>
+struct S1
+{
+};
+
+template<class T, template<class T>  class A, template<class T>  class B = A>
+struct C
+{
+  B<T> m;
+};
+
+void
+foo()
+{
+  C<int, S0> s;
+  S0<int> s0;
+
+  s.m = s0;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-9.C b/gcc/testsuite/g++.dg/template/canon-type-9.C
new file mode 100644
index 0000000..de6170e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-9.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-options "-std=c++0x" }
+// { dg-do "compile" }
+
+struct F { F(int) {}};
+
+template<class T, T* u>
+struct S
+{
+  decltype(u) foo(T);
+};
+
+template<class T, T *u>
+T* S<T, u>::foo(T)
+{
+  T t;
+  return t;
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..318deef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+template<class T, class U = int>
+struct S0
+{
+  typedef int const_iterator;
+};
+
+template<class T>
+struct Test
+{
+  typedef S0<T> SAlias;
+  typedef typename SAlias::const_iterator const_iterator;
+  const_iterator begin ();
+};
+
+template<class T>
+typename S0<T>::const_iterator
+Test<T>::begin()
+{
+  return 0;
+}

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-20 21:10                                       ` Dodji Seketeli
@ 2010-10-20 21:21                                         ` Jason Merrill
  2010-10-20 22:06                                           ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Jason Merrill @ 2010-10-20 21:21 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, H.J. Lu, GCC Patches

On 10/20/2010 04:50 PM, Dodji Seketeli wrote:
> +  if (TREE_PURPOSE (parm_desc)
> +      && dependent_type_p (TREE_TYPE (TREE_PURPOSE (parm_desc))))
> +    TREE_PURPOSE (parm_desc) =
> +      tsubst_template_arg (TREE_PURPOSE (parm_desc), arglist,
> +			   tf_warning_or_error, parm);

Using dependent_type_p here seems wrong; a template argument can involve 
template parameters even if it doesn't have a dependent type.  Can we 
just drop that test?

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-20 21:21                                         ` Jason Merrill
@ 2010-10-20 22:06                                           ` Dodji Seketeli
  2010-10-21  1:06                                             ` Jason Merrill
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-10-20 22:06 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, H.J. Lu, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 10/20/2010 04:50 PM, Dodji Seketeli wrote:
>> +  if (TREE_PURPOSE (parm_desc)
>> +      && dependent_type_p (TREE_TYPE (TREE_PURPOSE (parm_desc))))
>> +    TREE_PURPOSE (parm_desc) =
>> +      tsubst_template_arg (TREE_PURPOSE (parm_desc), arglist,
>> +			   tf_warning_or_error, parm);
>
> Using dependent_type_p here seems wrong; a template argument can
> involve template parameters even if it doesn't have a dependent type.
> Can we just drop that test?

Okay. I have relaunched the full regstrapping with the patch below.

-- 
	Dodji

commit 5c3197ce0dba90d0393d26a649a8fc8e5c735944
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for dependent typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
    	(struct template_parm_index_s)<num_siblings>: New field.
    	(TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
    	(fixup_template_parm, fixup_template_parms): New private
    	functions.
    	(current_template_args): Declare this.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(build_template_parm_index): Add a new argument to carry the total
    	number of template parms.
    	(reduce_template_parm_level, process_template_parm, make_auto): Adjust.
    	(current_template_args): Fix this for template template
    	parameters.
    	(tsubst_template_parm): Split out of ...
    	(tsubst_template_parms): ... this.
    	(reduce_template_parm_level): Don't loose
    	TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
    	(template_parm_to_arg): Extracted this function ...
    	(current_template_args): ... from this one.
    	(end_template_parm_list): Do not update template sibling parms
    	here anymore. Use fixup_template_parms instead.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
    	using all the arguments deduced so far.
    	(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
    	canonical_type_parameter.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore.
    	(comp_template_parms_position): Re-organized. Take the length of
    	template parms list in account.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* g++.dg/template/typedef36.C: New test.
    	* gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
    	* g++.dg/template/canon-type-10.C: Likewise.
    	* g++.dg/template/canon-type-11.C: Likewise.
    	* g++.dg/template/canon-type-12.C: Likewise.
    	* g++.dg/template/canon-type-13.C: Likewise.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f76c2be..d03b5b1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6690,7 +6690,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 626e452..1c009e5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -236,6 +236,7 @@ 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;
@@ -4306,6 +4307,9 @@ 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)
@@ -4327,10 +4331,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5012,7 +5012,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5348,7 +5348,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f27e7d6..0c64661 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8b2e542..0a93da8 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8c0129b..26eeca7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11026,6 +11026,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms.  We first need to know
+     the total number of template parms to be able to compute proper
+     canonical types of each dependent type. So after the loop, when
+     we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11044,11 +11051,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 85a5ea5..4d1e1f3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -137,7 +137,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, tree, tree);
+static tree build_template_parm_index (int, 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);
@@ -190,6 +190,12 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree template_parm_to_arg (tree t);
+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 void fixup_template_parms (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3346,12 +3352,14 @@ check_template_shadow (tree decl)
 }
 
 /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
-   ORIG_LEVEL, DECL, and TYPE.  */
+   ORIG_LEVEL, DECL, and TYPE.  NUM_SIBLINGS is the total number of
+   template parameters.  */
 
 static tree
 build_template_parm_index (int index,
 			   int level,
 			   int orig_level,
+			   int num_siblings,
 			   tree decl,
 			   tree type)
 {
@@ -3359,6 +3367,7 @@ 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);
@@ -3370,6 +3379,7 @@ build_template_parm_index (int index,
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
    if no such parameter existed.  */
+
 static tree
 canonical_type_parameter (tree type)
 {
@@ -3423,6 +3433,7 @@ 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) 
@@ -3438,15 +3449,20 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter shall
+   be set to 0.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3521,6 +3537,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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)) 
@@ -3554,6 +3571,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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);
@@ -3586,16 +3604,311 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
-	      current_template_parms;
     }
 
+  fixup_template_parms ();
+
   --processing_template_parmlist;
 
   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 = copy_type (type);
+  /* 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 = 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)
+    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. 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);
+
+  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;
+      int j;
+
+      /* First, fix up the type of the parm.  */
+
+      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);
+
+      /* Now we need to substitute the template parm types that
+	 have been fixed up so far into the non-type 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.
+
+	 Sot 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);
+
+	  /* Only substitute into template non-type parms.  */
+	  if (parameter != NULL_TREE
+	      && TREE_CODE (parameter) == TREE_LIST
+	      && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
+		  || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
+	    continue;
+
+	  if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
+	    continue;
+
+	  fixup_template_parm (parameter, j,
+			       TREE_VEC_LENGTH (tparms),
+			       targs);
+	}
+    }
+  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_warning_or_error, NULL_TREE);
+    }
+
+  TREE_PURPOSE (parm_desc) =
+    tsubst_template_arg (TREE_PURPOSE (parm_desc), arglist,
+			 tf_warning_or_error, parm);
+}
+
+/* Walk current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static 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);
+
+  fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+  /* 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
@@ -3613,6 +3926,65 @@ end_template_decl (void)
   current_template_parms = TREE_CHAIN (current_template_parms);
 }
 
+/* Takes a TREE_LIST representing a template parameter and convert it
+   into an argument suitable to be passed to the type substitution
+   functions.  */
+
+static tree
+template_parm_to_arg (tree t)
+{
+
+  if (t == NULL_TREE
+      || TREE_CODE (t) != TREE_LIST
+      || error_operand_p (TREE_VALUE (t)))
+    return t;
+
+  t = TREE_VALUE (t);
+
+  if (TREE_CODE (t) == TYPE_DECL
+      || TREE_CODE (t) == TEMPLATE_DECL)
+    {
+      t = TREE_TYPE (t);
+
+      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a TYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t = cxx_make_type (TYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	}
+    }
+  else
+    {
+      t = DECL_INITIAL (t);
+
+      if (TEMPLATE_PARM_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a NONTYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+	  tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t  = make_node (NONTYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	  TREE_TYPE (t) = type;
+	}
+    }
+  return t;
+}
+
 /* Within the declaration of a template, return all levels of template
    parameters that apply.  The template parameters are represented as
    a TREE_VEC, in the form documented in cp-tree.h for template
@@ -3639,63 +4011,7 @@ current_template_args (void)
 
       TREE_TYPE (a) = NULL_TREE;
       for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
-	{
-	  tree t = TREE_VEC_ELT (a, i);
-
-	  /* T will be a list if we are called from within a
-	     begin/end_template_parm_list pair, but a vector directly
-	     if within a begin/end_member_template_processing pair.  */
-	  if (TREE_CODE (t) == TREE_LIST)
-	    {
-	      t = TREE_VALUE (t);
-
-	      if (!error_operand_p (t))
-		{
-		  if (TREE_CODE (t) == TYPE_DECL
-		      || TREE_CODE (t) == TEMPLATE_DECL)
-                    {
-                      t = TREE_TYPE (t);
-                      
-                      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a TYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t = cxx_make_type (TYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                        }
-                    }
-                  else
-                    {
-                      t = DECL_INITIAL (t);
-                      
-                      if (TEMPLATE_PARM_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a NONTYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-                          tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t  = make_node (NONTYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                          TREE_TYPE (t) = type;
-                        }
-                    }
-		  TREE_VEC_ELT (a, i) = t;
-                }
-	    }
-	}
+	TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
 
 #ifdef ENABLE_CHECKING
       SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
@@ -3707,6 +4023,22 @@ current_template_args (void)
 	args = a;
     }
 
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.
+      */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -8744,8 +9076,6 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
 	{
           tree tuple;
-          tree default_value;
-          tree parm_decl;
 
           if (parms == error_mark_node)
             continue;
@@ -8755,18 +9085,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
           if (tuple == error_mark_node)
             continue;
 
-          default_value = TREE_PURPOSE (tuple);
-          parm_decl = TREE_VALUE (tuple);
-
-	  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
-	  if (TREE_CODE (parm_decl) == PARM_DECL
-	      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
-	    parm_decl = error_mark_node;
-	  default_value = tsubst_template_arg (default_value, args,
-					       complain, NULL_TREE);
-
-	  tuple = build_tree_list (default_value, parm_decl);
-	  TREE_VEC_ELT (new_vec, i) = tuple;
+	  TREE_VEC_ELT (new_vec, i) =
+	    tsubst_template_parm (tuple, args, complain);
 	}
 
       *new_parms =
@@ -8780,6 +9100,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Return the result of substituting ARGS into one template parameter
+   given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+   parameter and which TREE_PURPOSE is the default argument of the
+   template parameter.  */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+  tree default_value, parm_decl;
+
+  if (args == NULL_TREE
+      || t == NULL_TREE
+      || t == error_mark_node)
+    return t;
+
+  gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+  default_value = TREE_PURPOSE (t);
+  parm_decl = TREE_VALUE (t);
+
+  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+  if (TREE_CODE (parm_decl) == PARM_DECL
+      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+    parm_decl = error_mark_node;
+  default_value = tsubst_template_arg (default_value, args,
+				       complain, NULL_TREE);
+
+  return build_tree_list (default_value, parm_decl);
+}
+
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
@@ -14720,6 +15070,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  {
 	    tree parmvec = TYPE_TI_ARGS (parm);
 	    tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+	    tree full_argvec = add_to_template_args (targs, argvec);
 	    tree parm_parms 
               = DECL_INNERMOST_TEMPLATE_PARMS
 	          (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14754,7 +15105,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	      the global operator+ will be used; if they are not, the
 	      Lvalue_proxy will be converted to float.  */
 	    if (coerce_template_parms (parm_parms,
-                                       argvec,
+                                       full_argvec,
 				       TYPE_TI_TEMPLATE (parm),
 				       tf_none,
 				       /*require_all_args=*/true,
@@ -18428,7 +18779,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,
-     TYPE_NAME (au), NULL_TREE);
+     0, 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 b8f76b0..7e33693 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1062,22 +1062,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index 160198b..76d6f12 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
 static bool
 comp_template_parms_position (tree t1, tree t2)
 {
+  tree index1, index2;
   gcc_assert (t1 && t2
 	      && TREE_CODE (t1) == TREE_CODE (t2)
 	      && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
+  index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
+  index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
 
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* 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;
 
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
+      || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
+      || (TEMPLATE_PARM_PARAMETER_PACK (index1)
+	  != TEMPLATE_PARM_PARAMETER_PACK (index2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1301,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1407,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* If T1 and T2 don't have the same relative position in their
+	 template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+	return false;
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/canon-type-10.C b/gcc/testsuite/g++.dg/template/canon-type-10.C
new file mode 100644
index 0000000..0c38946
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-10.C
@@ -0,0 +1,23 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U = TT<int, C> >
+struct S
+{
+  void foo(TT<T, C>);
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U>
+void
+S<T, TT, U>::foo(TT<T, C>)
+{
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-11.C b/gcc/testsuite/g++.dg/template/canon-type-11.C
new file mode 100644
index 0000000..698fe31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-11.C
@@ -0,0 +1,39 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+  void bar();
+};
+
+template<class T>
+void
+C<T>::bar()
+{
+}
+
+
+template<class U,
+	 template<class TT0_T0> class TT0 = C,
+	 template<class TT1_T0> class TT1 = TT0>
+struct S
+{
+  C<U> s;
+
+  void foo(TT1<U>);
+
+  void bar()
+  {
+    foo(s);
+  }
+};
+
+template<class T,
+	 template<class TT0_T0> class TT0,
+	 template<class TT1_T0> class TT1>
+void
+S<T, TT0, TT1>::foo(TT1<T>)
+{
+  C<T> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-12.C b/gcc/testsuite/g++.dg/template/canon-type-12.C
new file mode 100644
index 0000000..694cc5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-12.C
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+
+template<class T, T t = (T)0>
+struct S
+{
+  void
+  foo(decltype(t) = t);
+};
+
+template<class T, T t>
+void
+S<T, t>::foo(T)
+{
+}
+
+void
+bar()
+{
+  S<int> s;
+  s.foo();
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-13.C b/gcc/testsuite/g++.dg/template/canon-type-13.C
new file mode 100644
index 0000000..ca39cea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-13.C
@@ -0,0 +1,27 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct S0
+{
+};
+
+template<class T>
+struct S1
+{
+};
+
+template<class T, template<class T>  class A, template<class T>  class B = A>
+struct C
+{
+  B<T> m;
+};
+
+void
+foo()
+{
+  C<int, S0> s;
+  S0<int> s0;
+
+  s.m = s0;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-9.C b/gcc/testsuite/g++.dg/template/canon-type-9.C
new file mode 100644
index 0000000..de6170e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-9.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-options "-std=c++0x" }
+// { dg-do "compile" }
+
+struct F { F(int) {}};
+
+template<class T, T* u>
+struct S
+{
+  decltype(u) foo(T);
+};
+
+template<class T, T *u>
+T* S<T, u>::foo(T)
+{
+  T t;
+  return t;
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..318deef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+template<class T, class U = int>
+struct S0
+{
+  typedef int const_iterator;
+};
+
+template<class T>
+struct Test
+{
+  typedef S0<T> SAlias;
+  typedef typename SAlias::const_iterator const_iterator;
+  const_iterator begin ();
+};
+
+template<class T>
+typename S0<T>::const_iterator
+Test<T>::begin()
+{
+  return 0;
+}

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-20 22:06                                           ` Dodji Seketeli
@ 2010-10-21  1:06                                             ` Jason Merrill
  2010-10-23 22:46                                               ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Jason Merrill @ 2010-10-21  1:06 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Paolo Carlini, H.J. Lu, GCC Patches

On 10/20/2010 05:37 PM, Dodji Seketeli wrote:
> +	  /* Only substitute into template non-type parms.  */
> +	  if (parameter != NULL_TREE
> +	      && TREE_CODE (parameter) == TREE_LIST
> +	      && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
> +		  || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
> +	    continue;
> +
> +	  if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
> +	    continue;

These optimizations seem unsafe:

template <class T, template <class U = T> class V> ...
template <class T, template <int I = T()> class U> ...

Let's handle all parms, and check in fixup_template_parm* to see if a 
parm has the right NUM_SIBLINGS before we try to adjust it; I would 
expect that the parms of a template template parm will already have 
NUM_SIBLINGS set properly, we just need to substitute in the outer parms.

> +	 Consider the level of the parms of TT; T and U both have
> +	 level 2; TT has no template parm of level 1. So in this case
> +	 the first element of full_template_args is NULL_TREE. If we
> +	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
> +	 of 2. This will make tsubst wrongly consider that T and U
> +	 have level 1. Instead, let's create a dummy vector as the
> +	 first element of full_template_args so that TMPL_ARG_DEPTH
> +	 returns the correct depth for args.
> +      */

The */ should go on the last line of text, not on a line by itself.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-21  1:06                                             ` Jason Merrill
@ 2010-10-23 22:46                                               ` Dodji Seketeli
  2010-10-23 23:39                                                 ` Jason Merrill
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-10-23 22:46 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Paolo Carlini, H.J. Lu, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 10/20/2010 05:37 PM, Dodji Seketeli wrote:
>> +	  /* Only substitute into template non-type parms.  */
>> +	  if (parameter != NULL_TREE
>> +	      && TREE_CODE (parameter) == TREE_LIST
>> +	      && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
>> +		  || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
>> +	    continue;
>> +
>> +	  if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
>> +	    continue;
>
> These optimizations seem unsafe:
>
> template <class T, template <class U = T> class V> ...
> template <class T, template <int I = T()> class U> ...
>
> Let's handle all parms, and check in fixup_template_parm* to see if a
> parm has the right NUM_SIBLINGS before we try to adjust it; I would
> expect that the parms of a template template parm will already have
> NUM_SIBLINGS set properly, we just need to substitute in the outer
> parms.

Done. It happened that tsubst* does access checking so we emit access
related errors twice; once during the type fixup and once later as we
were doing before. fixup_template_parm now disables access checking
using push_deferring_access_checks.

We also catch more errors at this point. In template/crash55.C, we have
this:

template<typename class T, T = T()> struct A {};

Now that the default argument goes through tsubst we emit this message:

test.cc:1:34: error: a cast to a type other than an integral or
enumeration type cannot appear in a constant-expression

I don't know if the error message is useful, but I believe it's
correct. So I adjusted the test.

>> +	 Consider the level of the parms of TT; T and U both have
>> +	 level 2; TT has no template parm of level 1. So in this case
>> +	 the first element of full_template_args is NULL_TREE. If we
>> +	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
>> +	 of 2. This will make tsubst wrongly consider that T and U
>> +	 have level 1. Instead, let's create a dummy vector as the
>> +	 first element of full_template_args so that TMPL_ARG_DEPTH
>> +	 returns the correct depth for args.
>> +      */
>
> The */ should go on the last line of text, not on a line by itself.
>

Fixed.

I have tested the patch below on x86-64-unknown-linux-gnu

-- 
	Dodji

commit 9c3747e5f7be2f49c47251495cade3471a9ef988
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for dependent typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
    	(struct template_parm_index_s)<num_siblings>: New field.
    	(TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
    	(fixup_template_parm, fixup_template_parms): New private
    	functions.
    	(current_template_args): Declare this.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(build_template_parm_index): Add a new argument to carry the total
    	number of template parms.
    	(reduce_template_parm_level, process_template_parm, make_auto): Adjust.
    	(current_template_args): Fix this for template template
    	parameters.
    	(tsubst_template_parm): Split out of ...
    	(tsubst_template_parms): ... this.
    	(reduce_template_parm_level): Don't loose
    	TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
    	(template_parm_to_arg): Extracted this function ...
    	(current_template_args): ... from this one.
    	(end_template_parm_list): Do not update template sibling parms
    	here anymore. Use fixup_template_parms instead.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
    	using all the arguments deduced so far.
    	(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
    	canonical_type_parameter.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore.
    	(comp_template_parms_position): Re-organized. Take the length of
    	template parms list in account.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* gcc/testsuite/g++.dg/template/crash55.C: Adjust.
    	* g++.dg/template/typedef36.C: New test.
    	* gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
    	* g++.dg/template/canon-type-10.C: Likewise.
    	* g++.dg/template/canon-type-11.C: Likewise.
    	* g++.dg/template/canon-type-12.C: Likewise.
    	* g++.dg/template/canon-type-13.C: Likewise.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f76c2be..d03b5b1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6690,7 +6690,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 626e452..1c009e5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -236,6 +236,7 @@ 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;
@@ -4306,6 +4307,9 @@ 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)
@@ -4327,10 +4331,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5012,7 +5012,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5348,7 +5348,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f27e7d6..0c64661 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8b2e542..0a93da8 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8c0129b..26eeca7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11026,6 +11026,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms.  We first need to know
+     the total number of template parms to be able to compute proper
+     canonical types of each dependent type. So after the loop, when
+     we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11044,11 +11051,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 85a5ea5..263b939 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -137,7 +137,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, tree, tree);
+static tree build_template_parm_index (int, 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);
@@ -190,6 +190,12 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree template_parm_to_arg (tree t);
+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 void fixup_template_parms (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3346,12 +3352,14 @@ check_template_shadow (tree decl)
 }
 
 /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
-   ORIG_LEVEL, DECL, and TYPE.  */
+   ORIG_LEVEL, DECL, and TYPE.  NUM_SIBLINGS is the total number of
+   template parameters.  */
 
 static tree
 build_template_parm_index (int index,
 			   int level,
 			   int orig_level,
+			   int num_siblings,
 			   tree decl,
 			   tree type)
 {
@@ -3359,6 +3367,7 @@ 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);
@@ -3370,6 +3379,7 @@ build_template_parm_index (int index,
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
    if no such parameter existed.  */
+
 static tree
 canonical_type_parameter (tree type)
 {
@@ -3423,6 +3433,7 @@ 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) 
@@ -3438,15 +3449,20 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter shall
+   be set to 0.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3521,6 +3537,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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)) 
@@ -3554,6 +3571,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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);
@@ -3586,16 +3604,323 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
-	      current_template_parms;
     }
 
+  fixup_template_parms ();
+
   --processing_template_parmlist;
 
   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;
+      int j;
+
+      /* First, fix up the type of the parm.  */
+
+      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);
+
+      /* Now we need to substitute the template parm types that
+	 have been fixed up so far into the non-type 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.
+
+	 Sot 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);
+
+	  /* Only substitute into template non-type parms.  */
+	  if (parameter != NULL_TREE
+	      && TREE_CODE (parameter) == TREE_LIST
+	      && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
+		  || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
+	    continue;
+
+	  if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
+	    continue;
+
+	  fixup_template_parm (parameter, j,
+			       TREE_VEC_LENGTH (tparms),
+			       targs);
+	}
+    }
+  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_warning_or_error, NULL_TREE);
+    }
+
+  TREE_PURPOSE (parm_desc) =
+    tsubst_template_arg (TREE_PURPOSE (parm_desc), arglist,
+			 tf_warning_or_error, parm);
+
+  pop_deferring_access_checks ();
+}
+
+/* Walk current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static 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);
+
+  fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+  /* 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
@@ -3613,6 +3938,65 @@ end_template_decl (void)
   current_template_parms = TREE_CHAIN (current_template_parms);
 }
 
+/* Takes a TREE_LIST representing a template parameter and convert it
+   into an argument suitable to be passed to the type substitution
+   functions.  */
+
+static tree
+template_parm_to_arg (tree t)
+{
+
+  if (t == NULL_TREE
+      || TREE_CODE (t) != TREE_LIST
+      || error_operand_p (TREE_VALUE (t)))
+    return t;
+
+  t = TREE_VALUE (t);
+
+  if (TREE_CODE (t) == TYPE_DECL
+      || TREE_CODE (t) == TEMPLATE_DECL)
+    {
+      t = TREE_TYPE (t);
+
+      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a TYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t = cxx_make_type (TYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	}
+    }
+  else
+    {
+      t = DECL_INITIAL (t);
+
+      if (TEMPLATE_PARM_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a NONTYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+	  tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t  = make_node (NONTYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	  TREE_TYPE (t) = type;
+	}
+    }
+  return t;
+}
+
 /* Within the declaration of a template, return all levels of template
    parameters that apply.  The template parameters are represented as
    a TREE_VEC, in the form documented in cp-tree.h for template
@@ -3639,63 +4023,7 @@ current_template_args (void)
 
       TREE_TYPE (a) = NULL_TREE;
       for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
-	{
-	  tree t = TREE_VEC_ELT (a, i);
-
-	  /* T will be a list if we are called from within a
-	     begin/end_template_parm_list pair, but a vector directly
-	     if within a begin/end_member_template_processing pair.  */
-	  if (TREE_CODE (t) == TREE_LIST)
-	    {
-	      t = TREE_VALUE (t);
-
-	      if (!error_operand_p (t))
-		{
-		  if (TREE_CODE (t) == TYPE_DECL
-		      || TREE_CODE (t) == TEMPLATE_DECL)
-                    {
-                      t = TREE_TYPE (t);
-                      
-                      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a TYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t = cxx_make_type (TYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                        }
-                    }
-                  else
-                    {
-                      t = DECL_INITIAL (t);
-                      
-                      if (TEMPLATE_PARM_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a NONTYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-                          tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t  = make_node (NONTYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                          TREE_TYPE (t) = type;
-                        }
-                    }
-		  TREE_VEC_ELT (a, i) = t;
-                }
-	    }
-	}
+	TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
 
 #ifdef ENABLE_CHECKING
       SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
@@ -3707,6 +4035,21 @@ current_template_args (void)
 	args = a;
     }
 
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.  */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -8744,8 +9087,6 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
 	{
           tree tuple;
-          tree default_value;
-          tree parm_decl;
 
           if (parms == error_mark_node)
             continue;
@@ -8755,18 +9096,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
           if (tuple == error_mark_node)
             continue;
 
-          default_value = TREE_PURPOSE (tuple);
-          parm_decl = TREE_VALUE (tuple);
-
-	  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
-	  if (TREE_CODE (parm_decl) == PARM_DECL
-	      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
-	    parm_decl = error_mark_node;
-	  default_value = tsubst_template_arg (default_value, args,
-					       complain, NULL_TREE);
-
-	  tuple = build_tree_list (default_value, parm_decl);
-	  TREE_VEC_ELT (new_vec, i) = tuple;
+	  TREE_VEC_ELT (new_vec, i) =
+	    tsubst_template_parm (tuple, args, complain);
 	}
 
       *new_parms =
@@ -8780,6 +9111,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Return the result of substituting ARGS into one template parameter
+   given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+   parameter and which TREE_PURPOSE is the default argument of the
+   template parameter.  */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+  tree default_value, parm_decl;
+
+  if (args == NULL_TREE
+      || t == NULL_TREE
+      || t == error_mark_node)
+    return t;
+
+  gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+  default_value = TREE_PURPOSE (t);
+  parm_decl = TREE_VALUE (t);
+
+  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+  if (TREE_CODE (parm_decl) == PARM_DECL
+      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+    parm_decl = error_mark_node;
+  default_value = tsubst_template_arg (default_value, args,
+				       complain, NULL_TREE);
+
+  return build_tree_list (default_value, parm_decl);
+}
+
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
@@ -14720,6 +15081,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  {
 	    tree parmvec = TYPE_TI_ARGS (parm);
 	    tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+	    tree full_argvec = add_to_template_args (targs, argvec);
 	    tree parm_parms 
               = DECL_INNERMOST_TEMPLATE_PARMS
 	          (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14754,7 +15116,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	      the global operator+ will be used; if they are not, the
 	      Lvalue_proxy will be converted to float.  */
 	    if (coerce_template_parms (parm_parms,
-                                       argvec,
+                                       full_argvec,
 				       TYPE_TI_TEMPLATE (parm),
 				       tf_none,
 				       /*require_all_args=*/true,
@@ -18428,7 +18790,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,
-     TYPE_NAME (au), NULL_TREE);
+     0, 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 b8f76b0..7e33693 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1062,22 +1062,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index 160198b..76d6f12 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
 static bool
 comp_template_parms_position (tree t1, tree t2)
 {
+  tree index1, index2;
   gcc_assert (t1 && t2
 	      && TREE_CODE (t1) == TREE_CODE (t2)
 	      && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
+  index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
+  index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
 
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* 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;
 
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
+      || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
+      || (TEMPLATE_PARM_PARAMETER_PACK (index1)
+	  != TEMPLATE_PARM_PARAMETER_PACK (index2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1301,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1407,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* If T1 and T2 don't have the same relative position in their
+	 template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+	return false;
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/canon-type-10.C b/gcc/testsuite/g++.dg/template/canon-type-10.C
new file mode 100644
index 0000000..0c38946
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-10.C
@@ -0,0 +1,23 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U = TT<int, C> >
+struct S
+{
+  void foo(TT<T, C>);
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U>
+void
+S<T, TT, U>::foo(TT<T, C>)
+{
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-11.C b/gcc/testsuite/g++.dg/template/canon-type-11.C
new file mode 100644
index 0000000..698fe31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-11.C
@@ -0,0 +1,39 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+  void bar();
+};
+
+template<class T>
+void
+C<T>::bar()
+{
+}
+
+
+template<class U,
+	 template<class TT0_T0> class TT0 = C,
+	 template<class TT1_T0> class TT1 = TT0>
+struct S
+{
+  C<U> s;
+
+  void foo(TT1<U>);
+
+  void bar()
+  {
+    foo(s);
+  }
+};
+
+template<class T,
+	 template<class TT0_T0> class TT0,
+	 template<class TT1_T0> class TT1>
+void
+S<T, TT0, TT1>::foo(TT1<T>)
+{
+  C<T> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-12.C b/gcc/testsuite/g++.dg/template/canon-type-12.C
new file mode 100644
index 0000000..694cc5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-12.C
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+
+template<class T, T t = (T)0>
+struct S
+{
+  void
+  foo(decltype(t) = t);
+};
+
+template<class T, T t>
+void
+S<T, t>::foo(T)
+{
+}
+
+void
+bar()
+{
+  S<int> s;
+  s.foo();
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-13.C b/gcc/testsuite/g++.dg/template/canon-type-13.C
new file mode 100644
index 0000000..ca39cea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-13.C
@@ -0,0 +1,27 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct S0
+{
+};
+
+template<class T>
+struct S1
+{
+};
+
+template<class T, template<class T>  class A, template<class T>  class B = A>
+struct C
+{
+  B<T> m;
+};
+
+void
+foo()
+{
+  C<int, S0> s;
+  S0<int> s0;
+
+  s.m = s0;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-9.C b/gcc/testsuite/g++.dg/template/canon-type-9.C
new file mode 100644
index 0000000..de6170e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-9.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-options "-std=c++0x" }
+// { dg-do "compile" }
+
+struct F { F(int) {}};
+
+template<class T, T* u>
+struct S
+{
+  decltype(u) foo(T);
+};
+
+template<class T, T *u>
+T* S<T, u>::foo(T)
+{
+  T t;
+  return t;
+}
diff --git a/gcc/testsuite/g++.dg/template/crash55.C b/gcc/testsuite/g++.dg/template/crash55.C
index 7cf9f1e..c2a53e4 100644
--- a/gcc/testsuite/g++.dg/template/crash55.C
+++ b/gcc/testsuite/g++.dg/template/crash55.C
@@ -1,6 +1,6 @@
 //PR c++/27668
 
-template<typename class T, T = T()> // { dg-error "nested-name-specifier|two or more|valid type" }
+template<typename class T, T = T()> // { dg-error "nested-name-specifier|two or more|valid type|constant-expression" }
 struct A {};
 
 template<int> void foo(A<int>);     // { dg-error "mismatch|constant|template argument" }
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..318deef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+template<class T, class U = int>
+struct S0
+{
+  typedef int const_iterator;
+};
+
+template<class T>
+struct Test
+{
+  typedef S0<T> SAlias;
+  typedef typename SAlias::const_iterator const_iterator;
+  const_iterator begin ();
+};
+
+template<class T>
+typename S0<T>::const_iterator
+Test<T>::begin()
+{
+  return 0;
+}

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-23 22:46                                               ` Dodji Seketeli
@ 2010-10-23 23:39                                                 ` Jason Merrill
  2010-10-24  2:33                                                   ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Jason Merrill @ 2010-10-23 23:39 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

On 10/23/2010 04:53 PM, Dodji Seketeli wrote:
> We also catch more errors at this point. In template/crash55.C, we have
> this:
>
> template<typename class T, T = T()>  struct A {};
>
> Now that the default argument goes through tsubst we emit this message:
>
> test.cc:1:34: error: a cast to a type other than an integral or
> enumeration type cannot appear in a constant-expression
>
> I don't know if the error message is useful, but I believe it's
> correct. So I adjusted the test.

No, it isn't correct; we need to allow T(), because T might be int when 
we instantiate the template.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-23 23:39                                                 ` Jason Merrill
@ 2010-10-24  2:33                                                   ` Dodji Seketeli
  2010-10-24  3:03                                                     ` Jason Merrill
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-10-24  2:33 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Jason Merrill <jason@redhat.com> a écrit:

> On 10/23/2010 04:53 PM, Dodji Seketeli wrote:
>> We also catch more errors at this point. In template/crash55.C, we have
>> this:
>>
>> template<typename class T, T = T()>  struct A {};
>>
>> Now that the default argument goes through tsubst we emit this message:
>>
>> test.cc:1:34: error: a cast to a type other than an integral or
>> enumeration type cannot appear in a constant-expression
>>
>> I don't know if the error message is useful, but I believe it's
>> correct. So I adjusted the test.
>
> No, it isn't correct; we need to allow T(), because T might be int
> when we instantiate the template.

If I change the declaration of T to make it correct, we don't have that
error message. It is because T is actually not properly declared that we
get the message. So should I just go back to using the tf_none argument
when tsubsting into the template parms/args altogether?

-- 
	Dodji

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-24  2:33                                                   ` Dodji Seketeli
@ 2010-10-24  3:03                                                     ` Jason Merrill
  2010-10-25 11:52                                                       ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Jason Merrill @ 2010-10-24  3:03 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

On 10/23/2010 05:32 PM, Dodji Seketeli wrote:
> If I change the declaration of T to make it correct, we don't have that
> error message.

Ah, I see.

> It is because T is actually not properly declared that we
> get the message. So should I just go back to using the tf_none argument
> when tsubsting into the template parms/args altogether?

I suppose so.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-24  3:03                                                     ` Jason Merrill
@ 2010-10-25 11:52                                                       ` Dodji Seketeli
  2010-10-27 15:59                                                         ` Dodji Seketeli
  0 siblings, 1 reply; 38+ messages in thread
From: Dodji Seketeli @ 2010-10-25 11:52 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Jason Merrill <jason@redhat.com> writes:
>> It is because T is actually not properly declared that we
>> get the message. So should I just go back to using the tf_none argument
>> when tsubsting into the template parms/args altogether?
>
> I suppose so.

OK. I did that in the patch below and tested it on
x86_64-unknown-linux-gnu against trunk.

-- 
	Dodji

commit 8052f1882d631b8835a3354a5e21e4c1f1ce6093
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for dependent typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
    	(struct template_parm_index_s)<num_siblings>: New field.
    	(TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
    	(fixup_template_parm, fixup_template_parms): New private
    	functions.
    	(current_template_args): Declare this.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(build_template_parm_index): Add a new argument to carry the total
    	number of template parms.
    	(reduce_template_parm_level, process_template_parm, make_auto): Adjust.
    	(current_template_args): Fix this for template template
    	parameters.
    	(tsubst_template_parm): Split out of ...
    	(tsubst_template_parms): ... this.
    	(reduce_template_parm_level): Don't loose
    	TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
    	(template_parm_to_arg): Extracted this function ...
    	(current_template_args): ... from this one.
    	(end_template_parm_list): Do not update template sibling parms
    	here anymore. Use fixup_template_parms instead.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
    	using all the arguments deduced so far.
    	(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
    	canonical_type_parameter.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore.
    	(comp_template_parms_position): Re-organized. Take the length of
    	template parms list in account.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* g++.dg/template/typedef36.C: New test.
    	* gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
    	* g++.dg/template/canon-type-10.C: Likewise.
    	* g++.dg/template/canon-type-11.C: Likewise.
    	* g++.dg/template/canon-type-12.C: Likewise.
    	* g++.dg/template/canon-type-13.C: Likewise.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f76c2be..d03b5b1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6690,7 +6690,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 626e452..1c009e5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -236,6 +236,7 @@ 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;
@@ -4306,6 +4307,9 @@ 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)
@@ -4327,10 +4331,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5012,7 +5012,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5348,7 +5348,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f27e7d6..0c64661 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8b2e542..0a93da8 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8c0129b..26eeca7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11026,6 +11026,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms.  We first need to know
+     the total number of template parms to be able to compute proper
+     canonical types of each dependent type. So after the loop, when
+     we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11044,11 +11051,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 85a5ea5..5305595 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -137,7 +137,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, tree, tree);
+static tree build_template_parm_index (int, 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);
@@ -190,6 +190,12 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree template_parm_to_arg (tree t);
+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 void fixup_template_parms (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3346,12 +3352,14 @@ check_template_shadow (tree decl)
 }
 
 /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
-   ORIG_LEVEL, DECL, and TYPE.  */
+   ORIG_LEVEL, DECL, and TYPE.  NUM_SIBLINGS is the total number of
+   template parameters.  */
 
 static tree
 build_template_parm_index (int index,
 			   int level,
 			   int orig_level,
+			   int num_siblings,
 			   tree decl,
 			   tree type)
 {
@@ -3359,6 +3367,7 @@ 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);
@@ -3370,6 +3379,7 @@ build_template_parm_index (int index,
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
    if no such parameter existed.  */
+
 static tree
 canonical_type_parameter (tree type)
 {
@@ -3423,6 +3433,7 @@ 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) 
@@ -3438,15 +3449,20 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter shall
+   be set to 0.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3521,6 +3537,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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)) 
@@ -3554,6 +3571,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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);
@@ -3586,16 +3604,323 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
-	      current_template_parms;
     }
 
+  fixup_template_parms ();
+
   --processing_template_parmlist;
 
   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;
+      int j;
+
+      /* First, fix up the type of the parm.  */
+
+      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);
+
+      /* Now we need to substitute the template parm types that
+	 have been fixed up so far into the non-type 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);
+
+	  /* Only substitute into template non-type parms.  */
+	  if (parameter != NULL_TREE
+	      && TREE_CODE (parameter) == TREE_LIST
+	      && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
+		  || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
+	    continue;
+
+	  if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
+	    continue;
+
+	  fixup_template_parm (parameter, j,
+			       TREE_VEC_LENGTH (tparms),
+			       targs);
+	}
+    }
+  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 current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static 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);
+
+  fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+  /* 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
@@ -3613,6 +3938,65 @@ end_template_decl (void)
   current_template_parms = TREE_CHAIN (current_template_parms);
 }
 
+/* Takes a TREE_LIST representing a template parameter and convert it
+   into an argument suitable to be passed to the type substitution
+   functions.  */
+
+static tree
+template_parm_to_arg (tree t)
+{
+
+  if (t == NULL_TREE
+      || TREE_CODE (t) != TREE_LIST
+      || error_operand_p (TREE_VALUE (t)))
+    return t;
+
+  t = TREE_VALUE (t);
+
+  if (TREE_CODE (t) == TYPE_DECL
+      || TREE_CODE (t) == TEMPLATE_DECL)
+    {
+      t = TREE_TYPE (t);
+
+      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a TYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t = cxx_make_type (TYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	}
+    }
+  else
+    {
+      t = DECL_INITIAL (t);
+
+      if (TEMPLATE_PARM_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a NONTYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+	  tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t  = make_node (NONTYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	  TREE_TYPE (t) = type;
+	}
+    }
+  return t;
+}
+
 /* Within the declaration of a template, return all levels of template
    parameters that apply.  The template parameters are represented as
    a TREE_VEC, in the form documented in cp-tree.h for template
@@ -3639,63 +4023,7 @@ current_template_args (void)
 
       TREE_TYPE (a) = NULL_TREE;
       for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
-	{
-	  tree t = TREE_VEC_ELT (a, i);
-
-	  /* T will be a list if we are called from within a
-	     begin/end_template_parm_list pair, but a vector directly
-	     if within a begin/end_member_template_processing pair.  */
-	  if (TREE_CODE (t) == TREE_LIST)
-	    {
-	      t = TREE_VALUE (t);
-
-	      if (!error_operand_p (t))
-		{
-		  if (TREE_CODE (t) == TYPE_DECL
-		      || TREE_CODE (t) == TEMPLATE_DECL)
-                    {
-                      t = TREE_TYPE (t);
-                      
-                      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a TYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t = cxx_make_type (TYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                        }
-                    }
-                  else
-                    {
-                      t = DECL_INITIAL (t);
-                      
-                      if (TEMPLATE_PARM_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a NONTYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-                          tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t  = make_node (NONTYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                          TREE_TYPE (t) = type;
-                        }
-                    }
-		  TREE_VEC_ELT (a, i) = t;
-                }
-	    }
-	}
+	TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
 
 #ifdef ENABLE_CHECKING
       SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
@@ -3707,6 +4035,21 @@ current_template_args (void)
 	args = a;
     }
 
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.  */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -8744,8 +9087,6 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
 	{
           tree tuple;
-          tree default_value;
-          tree parm_decl;
 
           if (parms == error_mark_node)
             continue;
@@ -8755,18 +9096,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
           if (tuple == error_mark_node)
             continue;
 
-          default_value = TREE_PURPOSE (tuple);
-          parm_decl = TREE_VALUE (tuple);
-
-	  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
-	  if (TREE_CODE (parm_decl) == PARM_DECL
-	      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
-	    parm_decl = error_mark_node;
-	  default_value = tsubst_template_arg (default_value, args,
-					       complain, NULL_TREE);
-
-	  tuple = build_tree_list (default_value, parm_decl);
-	  TREE_VEC_ELT (new_vec, i) = tuple;
+	  TREE_VEC_ELT (new_vec, i) =
+	    tsubst_template_parm (tuple, args, complain);
 	}
 
       *new_parms =
@@ -8780,6 +9111,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Return the result of substituting ARGS into one template parameter
+   given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+   parameter and which TREE_PURPOSE is the default argument of the
+   template parameter.  */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+  tree default_value, parm_decl;
+
+  if (args == NULL_TREE
+      || t == NULL_TREE
+      || t == error_mark_node)
+    return t;
+
+  gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+  default_value = TREE_PURPOSE (t);
+  parm_decl = TREE_VALUE (t);
+
+  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+  if (TREE_CODE (parm_decl) == PARM_DECL
+      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+    parm_decl = error_mark_node;
+  default_value = tsubst_template_arg (default_value, args,
+				       complain, NULL_TREE);
+
+  return build_tree_list (default_value, parm_decl);
+}
+
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
@@ -14720,6 +15081,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  {
 	    tree parmvec = TYPE_TI_ARGS (parm);
 	    tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+	    tree full_argvec = add_to_template_args (targs, argvec);
 	    tree parm_parms 
               = DECL_INNERMOST_TEMPLATE_PARMS
 	          (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14754,7 +15116,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	      the global operator+ will be used; if they are not, the
 	      Lvalue_proxy will be converted to float.  */
 	    if (coerce_template_parms (parm_parms,
-                                       argvec,
+                                       full_argvec,
 				       TYPE_TI_TEMPLATE (parm),
 				       tf_none,
 				       /*require_all_args=*/true,
@@ -18428,7 +18790,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,
-     TYPE_NAME (au), NULL_TREE);
+     0, 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 b8f76b0..7e33693 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1062,22 +1062,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index 160198b..76d6f12 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
 static bool
 comp_template_parms_position (tree t1, tree t2)
 {
+  tree index1, index2;
   gcc_assert (t1 && t2
 	      && TREE_CODE (t1) == TREE_CODE (t2)
 	      && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
+  index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
+  index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
 
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* 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;
 
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
+      || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
+      || (TEMPLATE_PARM_PARAMETER_PACK (index1)
+	  != TEMPLATE_PARM_PARAMETER_PACK (index2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1301,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1407,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* If T1 and T2 don't have the same relative position in their
+	 template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+	return false;
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/canon-type-10.C b/gcc/testsuite/g++.dg/template/canon-type-10.C
new file mode 100644
index 0000000..0c38946
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-10.C
@@ -0,0 +1,23 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U = TT<int, C> >
+struct S
+{
+  void foo(TT<T, C>);
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U>
+void
+S<T, TT, U>::foo(TT<T, C>)
+{
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-11.C b/gcc/testsuite/g++.dg/template/canon-type-11.C
new file mode 100644
index 0000000..698fe31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-11.C
@@ -0,0 +1,39 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+  void bar();
+};
+
+template<class T>
+void
+C<T>::bar()
+{
+}
+
+
+template<class U,
+	 template<class TT0_T0> class TT0 = C,
+	 template<class TT1_T0> class TT1 = TT0>
+struct S
+{
+  C<U> s;
+
+  void foo(TT1<U>);
+
+  void bar()
+  {
+    foo(s);
+  }
+};
+
+template<class T,
+	 template<class TT0_T0> class TT0,
+	 template<class TT1_T0> class TT1>
+void
+S<T, TT0, TT1>::foo(TT1<T>)
+{
+  C<T> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-12.C b/gcc/testsuite/g++.dg/template/canon-type-12.C
new file mode 100644
index 0000000..694cc5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-12.C
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+
+template<class T, T t = (T)0>
+struct S
+{
+  void
+  foo(decltype(t) = t);
+};
+
+template<class T, T t>
+void
+S<T, t>::foo(T)
+{
+}
+
+void
+bar()
+{
+  S<int> s;
+  s.foo();
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-13.C b/gcc/testsuite/g++.dg/template/canon-type-13.C
new file mode 100644
index 0000000..ca39cea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-13.C
@@ -0,0 +1,27 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct S0
+{
+};
+
+template<class T>
+struct S1
+{
+};
+
+template<class T, template<class T>  class A, template<class T>  class B = A>
+struct C
+{
+  B<T> m;
+};
+
+void
+foo()
+{
+  C<int, S0> s;
+  S0<int> s0;
+
+  s.m = s0;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-9.C b/gcc/testsuite/g++.dg/template/canon-type-9.C
new file mode 100644
index 0000000..de6170e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-9.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-options "-std=c++0x" }
+// { dg-do "compile" }
+
+struct F { F(int) {}};
+
+template<class T, T* u>
+struct S
+{
+  decltype(u) foo(T);
+};
+
+template<class T, T *u>
+T* S<T, u>::foo(T)
+{
+  T t;
+  return t;
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..318deef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+template<class T, class U = int>
+struct S0
+{
+  typedef int const_iterator;
+};
+
+template<class T>
+struct Test
+{
+  typedef S0<T> SAlias;
+  typedef typename SAlias::const_iterator const_iterator;
+  const_iterator begin ();
+};
+
+template<class T>
+typename S0<T>::const_iterator
+Test<T>::begin()
+{
+  return 0;
+}

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-25 11:52                                                       ` Dodji Seketeli
@ 2010-10-27 15:59                                                         ` Dodji Seketeli
  2010-10-28 17:54                                                           ` Jason Merrill
  2010-12-17 20:51                                                           ` H.J. Lu
  0 siblings, 2 replies; 38+ messages in thread
From: Dodji Seketeli @ 2010-10-27 15:59 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches

Hello,

So I forgot to remove the wrong "optimization" on the parms of
template template parameters. In the patch at the end of this message
this hunks fixes that:

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5305595..64a3f64 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3815,16 +3815,6 @@ fixup_template_parm (tree parm_desc,
 	  TREE_VEC_ELT (innermost_args, j) =
 	    template_parm_to_arg (parameter);
 
-	  /* Only substitute into template non-type parms.  */
-	  if (parameter != NULL_TREE
-	      && TREE_CODE (parameter) == TREE_LIST
-	      && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
-		  || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
-	    continue;
-
-	  if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
-	    continue;
-
 	  fixup_template_parm (parameter, j,
 			       TREE_VEC_LENGTH (tparms),
 			       targs);

Doing this uncovered an issue though. It boils down to tsubst* now
possibly seeing more invalid template parameter arguments.

As a first observation, consider this unvalid testcase:

template<template<typename... T, typename T1 = T> class V> struct B {};

The parameter T1 is invalid because T [being a variadic template
parameter T] should have been the last parameter.  At some point
current_template_args (so now template_parm_to_arg) builds a
TREE_LIST containing an error_mark_node to represent the invalid T1.

Later while substituting into a template parm tsubst sees an argument
that is a TREE_LIST containing an error_mark_node and that violates
the following assertion:

    if (code == TEMPLATE_TYPE_PARM)
      {
        int quals;
	gcc_assert (TYPE_P (arg)); // <-- arg is a TREE_LIST with an
                                   // error_mark_node here. Boom.

So after our offline discussion about this I modified
template_parm_to_arg to make its behaviour consistent in cases of an
invalid argumentr i.e. make the invalid argument be an error_mark_node
instead of a TREE_LIST containing an error_mark_node.

This is what the hunk below does:

@@ -3940,17 +3930,20 @@ end_template_decl (void)
 
 /* Takes a TREE_LIST representing a template parameter and convert it
    into an argument suitable to be passed to the type substitution
-   functions.  */
+   functions.  Note that If the TREE_LIST contains an error_mark
+   node, the returned argument is error_mark_node.  */
 
 static tree
 template_parm_to_arg (tree t)
 {
 
   if (t == NULL_TREE
-      || TREE_CODE (t) != TREE_LIST
-      || error_operand_p (TREE_VALUE (t)))
+      || TREE_CODE (t) != TREE_LIST)
     return t;
 
+  if (error_operand_p (TREE_VALUE (t)))
+    return error_mark_node;
+
   t = TREE_VALUE (t);
 
   if (TREE_CODE (t) == TYPE_DECL

But then some code breaks because it implicitely expects invalid args
to be represented as a TREE_LIST containing an error_mark_node.
E.g: in this example from testsuite/g++.dg/templates/void11.C:

template<void> struct A // #0 <-- the  template parm is invalid

{
  template<int> friend void foo(); // #1 <-- we shouldn't put foo in
                                   // the global scope symbol table b/c
				   // of [temp.inject/2]

};

void bar()
{
  foo<0>(); // <-- looking up foo should fail because foo is not visible
}

In our case, in #1, push_template_decl_real wrongly inserts foo in the
global scope symbol table because in this code

  if (new_template_p && !ctx
      && !(is_friend && template_class_depth (current_class_type) > 0))
    {
      tmpl = pushdecl_namespace_level (tmpl, is_friend);

template_class_depth (current_class_type) returns 0 even though
current_class_type (A in this case) is a template here. The problem is
that uses_template_parms fails to return true on the invalid template
parm. Making dependent_template_arg_p recognize error_mark_node as
being a dependent type fixes the problem:

@@ -18363,6 +18356,13 @@ dependent_template_arg_p (tree arg)
   if (!processing_template_decl)
     return false;
 
+  /* Assume a template argument that was wrongly written by the user
+     is dependent. This is consistent with what
+     any_dependent_template_arguments_p [that calls this function]
+     does.  */
+  if (arg == error_mark_node)
+    return true;
+
   if (TREE_CODE (arg) == TEMPLATE_DECL
       || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
     return dependent_template_p (arg);

Below is the fully updated patch. Fully bootstrapped and tested on
x86_64-unknown-linux-gnu.

-- 
	Dodji

commit c21c5f024f47a9a55facbd70c0d1f36956cff7c4
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Sep 13 12:12:21 2010 +0200

    Restore canonical type comparison for dependent typedefs
    
    gcc/cp/ChangeLog:
    	PR c++/45606
    	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
    	(struct template_parm_index_s)<num_siblings>: New field.
    	(TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
    	(process_template_parm): Extend the API to accept the number of
    	template parms in argument.
    	(cp_set_underlying_type): Remove this.
    	* class.c (build_self_reference): Require canonical type equality
    	back on the self reference of class.
    	* decl2.c (grokfield): Require canonical type equality back on
    	typedef class fields.
    	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
    	equality back on typedefs.
    	* parser.c (cp_parser_template_parameter_list): Do not require
    	canonical type equality on dependent types created during
    	template parameters parsing.
    	* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
    	(fixup_template_parm, fixup_template_parms): New private
    	functions.
    	(current_template_args): Declare this.
    	(process_template_parm): Pass the total number of template parms
    	to canonical_type_parameter.
    	(build_template_parm_index): Add a new argument to carry the total
    	number of template parms.
    	(reduce_template_parm_level, process_template_parm, make_auto): Adjust.
    	(current_template_args): Fix this for template template
    	parameters.
    	(tsubst_template_parm): Split out of ...
    	(tsubst_template_parms): ... this.
    	(reduce_template_parm_level): Don't loose
    	TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
    	(template_parm_to_arg): Extracted this function from
    	current_template_args. Make it represent invalid template parms
    	with an error_mark_node instead of a LIST_TREE containing an
    	error_mark_node.
    	(current_template_args): Use template_parm_to_arg.
    	(dependent_template_arg_p): Consider an invalid template argument
    	as dependent.
    	(end_template_parm_list): Do not update template sibling parms
    	here anymore. Use fixup_template_parms instead.
    	(process_template_parm): Pass the number of template parms to
    	canonical_type_parameter.
    	(make_auto): Require structural equality on auto
    	TEMPLATE_TYPE_PARM for now.
    	(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
    	using all the arguments deduced so far.
    	(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
    	canonical_type_parameter.
    	* tree.c (cp_set_underlying_type): Remove.
    	* typeck.c (get_template_parms_of_dependent_type)
    	(incompatible_dependent_types_p): Remove.
    	(structural_comptypes): Do not call incompatible_dependent_types_p
    	anymore.
    	(comp_template_parms_position): Re-organized. Take the length of
    	template parms list in account.
    
    gcc/testsuite/ChangeLog:
    	PR c++/45606
    	* g++.dg/template/typedef36.C: New test.
    	* gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
    	* g++.dg/template/canon-type-10.C: Likewise.
    	* g++.dg/template/canon-type-11.C: Likewise.
    	* g++.dg/template/canon-type-12.C: Likewise.
    	* g++.dg/template/canon-type-13.C: Likewise.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f76c2be..d03b5b1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6690,7 +6690,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
-  cp_set_underlying_type (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 626e452..1c009e5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -236,6 +236,7 @@ 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;
@@ -4306,6 +4307,9 @@ 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)
@@ -4327,10 +4331,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
   (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
-   TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
-  (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
 
 /* These constants can used as bit flags in the process of tree formatting.
 
@@ -5012,7 +5012,7 @@ 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);
+						 bool, bool, unsigned);
 extern tree end_template_parm_list		(tree);
 extern void end_template_decl			(void);
 extern tree maybe_update_decl_type		(tree, tree);
@@ -5348,7 +5348,6 @@ 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 void cp_set_underlying_type		(tree);
 extern tree copy_binfo				(tree, tree, tree,
 						 tree *, int);
 extern int member_p				(const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f27e7d6..0c64661 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
       if (declspecs->specs[(int)ds_typedef]
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-	cp_set_underlying_type (value);
+	set_underlying_type (value);
 
       return value;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8b2e542..0a93da8 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 		     inlining.  */
 		  && (!TYPE_NAME (type)
 		      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
-	    cp_set_underlying_type (x);
+	    set_underlying_type (x);
 
 	  if (type != error_mark_node
 	      && TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8c0129b..26eeca7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11026,6 +11026,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms.  We first need to know
+     the total number of template parms to be able to compute proper
+     canonical types of each dependent type. So after the loop, when
+     we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11044,11 +11051,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 						parm_loc,
 						parameter,
 						is_non_type,
-                                                is_parameter_pack);
+						is_parameter_pack,
+						0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 85a5ea5..64a3f64 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -137,7 +137,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, tree, tree);
+static tree build_template_parm_index (int, 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);
@@ -190,6 +190,12 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
 static tree listify (tree);
 static tree listify_autos (tree, tree);
+static tree template_parm_to_arg (tree t);
+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 void fixup_template_parms (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3346,12 +3352,14 @@ check_template_shadow (tree decl)
 }
 
 /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
-   ORIG_LEVEL, DECL, and TYPE.  */
+   ORIG_LEVEL, DECL, and TYPE.  NUM_SIBLINGS is the total number of
+   template parameters.  */
 
 static tree
 build_template_parm_index (int index,
 			   int level,
 			   int orig_level,
+			   int num_siblings,
 			   tree decl,
 			   tree type)
 {
@@ -3359,6 +3367,7 @@ 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);
@@ -3370,6 +3379,7 @@ build_template_parm_index (int index,
 /* Find the canonical type parameter for the given template type
    parameter.  Returns the canonical type parameter, which may be TYPE
    if no such parameter existed.  */
+
 static tree
 canonical_type_parameter (tree type)
 {
@@ -3423,6 +3433,7 @@ 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) 
@@ -3438,15 +3449,20 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
   return TEMPLATE_PARM_DESCENDANTS (index);
 }
 
-/* Process information from new template parameter PARM and append it to the
-   LIST being built.  This new parameter is a non-type parameter iff
-   IS_NON_TYPE is true. This new parameter is a parameter
-   pack iff IS_PARAMETER_PACK is true.  The location of PARM is in 
-   PARM_LOC.  */
+/* Process information from new template parameter PARM and append it
+   to the LIST being built.  This new parameter is a non-type
+   parameter iff IS_NON_TYPE is true. This new parameter is a
+   parameter pack iff IS_PARAMETER_PACK is true.  The location of PARM
+   is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+   parameter list PARM belongs to. This is used used to create a
+   proper canonical type for the type of PARM that is to be created,
+   iff PARM is a type.  If the size is not known, this parameter shall
+   be set to 0.  */
 
 tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type, 
-                       bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+		       bool is_non_type, bool is_parameter_pack,
+		       unsigned num_template_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3521,6 +3537,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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)) 
@@ -3554,6 +3571,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
       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);
@@ -3586,16 +3604,313 @@ end_template_parm_list (tree parms)
       next = TREE_CHAIN (parm);
       TREE_VEC_ELT (saved_parmlist, nparms) = parm;
       TREE_CHAIN (parm) = NULL_TREE;
-      if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-	TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
-	      current_template_parms;
     }
 
+  fixup_template_parms ();
+
   --processing_template_parmlist;
 
   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;
+      int j;
+
+      /* First, fix up the type of the parm.  */
+
+      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);
+
+      /* Now we need to substitute the template parm types that
+	 have been fixed up so far into the non-type 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);
+	}
+    }
+  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 current the template parms and properly compute the canonical
+   types of the dependent types created during
+   cp_parser_template_parameter_list.  */
+
+static 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);
+
+  fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+  /* 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
@@ -3613,6 +3928,68 @@ end_template_decl (void)
   current_template_parms = TREE_CHAIN (current_template_parms);
 }
 
+/* Takes a TREE_LIST representing a template parameter and convert it
+   into an argument suitable to be passed to the type substitution
+   functions.  Note that If the TREE_LIST contains an error_mark
+   node, the returned argument is error_mark_node.  */
+
+static tree
+template_parm_to_arg (tree t)
+{
+
+  if (t == NULL_TREE
+      || TREE_CODE (t) != TREE_LIST)
+    return t;
+
+  if (error_operand_p (TREE_VALUE (t)))
+    return error_mark_node;
+
+  t = TREE_VALUE (t);
+
+  if (TREE_CODE (t) == TYPE_DECL
+      || TREE_CODE (t) == TEMPLATE_DECL)
+    {
+      t = TREE_TYPE (t);
+
+      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a TYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t = cxx_make_type (TYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	}
+    }
+  else
+    {
+      t = DECL_INITIAL (t);
+
+      if (TEMPLATE_PARM_PARAMETER_PACK (t))
+	{
+	  /* Turn this argument into a NONTYPE_ARGUMENT_PACK
+	     with a single element, which expands T.  */
+	  tree vec = make_tree_vec (1);
+	  tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+	  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+	    (vec, TREE_VEC_LENGTH (vec));
+#endif
+	  TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+	  t  = make_node (NONTYPE_ARGUMENT_PACK);
+	  SET_ARGUMENT_PACK_ARGS (t, vec);
+	  TREE_TYPE (t) = type;
+	}
+    }
+  return t;
+}
+
 /* Within the declaration of a template, return all levels of template
    parameters that apply.  The template parameters are represented as
    a TREE_VEC, in the form documented in cp-tree.h for template
@@ -3639,63 +4016,7 @@ current_template_args (void)
 
       TREE_TYPE (a) = NULL_TREE;
       for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
-	{
-	  tree t = TREE_VEC_ELT (a, i);
-
-	  /* T will be a list if we are called from within a
-	     begin/end_template_parm_list pair, but a vector directly
-	     if within a begin/end_member_template_processing pair.  */
-	  if (TREE_CODE (t) == TREE_LIST)
-	    {
-	      t = TREE_VALUE (t);
-
-	      if (!error_operand_p (t))
-		{
-		  if (TREE_CODE (t) == TYPE_DECL
-		      || TREE_CODE (t) == TEMPLATE_DECL)
-                    {
-                      t = TREE_TYPE (t);
-                      
-                      if (TEMPLATE_TYPE_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a TYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t = cxx_make_type (TYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                        }
-                    }
-                  else
-                    {
-                      t = DECL_INITIAL (t);
-                      
-                      if (TEMPLATE_PARM_PARAMETER_PACK (t))
-                        {
-                          /* Turn this argument into a NONTYPE_ARGUMENT_PACK
-                             with a single element, which expands T.  */
-                          tree vec = make_tree_vec (1);
-                          tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
-#ifdef ENABLE_CHECKING
-			  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
-				(vec, TREE_VEC_LENGTH (vec));
-#endif
-                          TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-                          
-                          t  = make_node (NONTYPE_ARGUMENT_PACK);
-                          SET_ARGUMENT_PACK_ARGS (t, vec);
-                          TREE_TYPE (t) = type;
-                        }
-                    }
-		  TREE_VEC_ELT (a, i) = t;
-                }
-	    }
-	}
+	TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
 
 #ifdef ENABLE_CHECKING
       SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
@@ -3707,6 +4028,21 @@ current_template_args (void)
 	args = a;
     }
 
+    if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+      /* This can happen for template parms of a template template
+	 parameter, e.g:
+
+	 template<template<class T, class U> class TT> struct S;
+
+	 Consider the level of the parms of TT; T and U both have
+	 level 2; TT has no template parm of level 1. So in this case
+	 the first element of full_template_args is NULL_TREE. If we
+	 leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+	 of 2. This will make tsubst wrongly consider that T and U
+	 have level 1. Instead, let's create a dummy vector as the
+	 first element of full_template_args so that TMPL_ARG_DEPTH
+	 returns the correct depth for args.  */
+      TREE_VEC_ELT (args, 0) = make_tree_vec (1);
   return args;
 }
 
@@ -8744,8 +9080,6 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
 	{
           tree tuple;
-          tree default_value;
-          tree parm_decl;
 
           if (parms == error_mark_node)
             continue;
@@ -8755,18 +9089,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
           if (tuple == error_mark_node)
             continue;
 
-          default_value = TREE_PURPOSE (tuple);
-          parm_decl = TREE_VALUE (tuple);
-
-	  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
-	  if (TREE_CODE (parm_decl) == PARM_DECL
-	      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
-	    parm_decl = error_mark_node;
-	  default_value = tsubst_template_arg (default_value, args,
-					       complain, NULL_TREE);
-
-	  tuple = build_tree_list (default_value, parm_decl);
-	  TREE_VEC_ELT (new_vec, i) = tuple;
+	  TREE_VEC_ELT (new_vec, i) =
+	    tsubst_template_parm (tuple, args, complain);
 	}
 
       *new_parms =
@@ -8780,6 +9104,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   return r;
 }
 
+/* Return the result of substituting ARGS into one template parameter
+   given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+   parameter and which TREE_PURPOSE is the default argument of the
+   template parameter.  */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+  tree default_value, parm_decl;
+
+  if (args == NULL_TREE
+      || t == NULL_TREE
+      || t == error_mark_node)
+    return t;
+
+  gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+  default_value = TREE_PURPOSE (t);
+  parm_decl = TREE_VALUE (t);
+
+  parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+  if (TREE_CODE (parm_decl) == PARM_DECL
+      && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+    parm_decl = error_mark_node;
+  default_value = tsubst_template_arg (default_value, args,
+				       complain, NULL_TREE);
+
+  return build_tree_list (default_value, parm_decl);
+}
+
 /* Substitute the ARGS into the indicated aggregate (or enumeration)
    type T.  If T is not an aggregate or enumeration type, it is
    handled as if by tsubst.  IN_DECL is as for tsubst.  If
@@ -14720,6 +15074,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	  {
 	    tree parmvec = TYPE_TI_ARGS (parm);
 	    tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+	    tree full_argvec = add_to_template_args (targs, argvec);
 	    tree parm_parms 
               = DECL_INNERMOST_TEMPLATE_PARMS
 	          (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14754,7 +15109,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 	      the global operator+ will be used; if they are not, the
 	      Lvalue_proxy will be converted to float.  */
 	    if (coerce_template_parms (parm_parms,
-                                       argvec,
+                                       full_argvec,
 				       TYPE_TI_TEMPLATE (parm),
 				       tf_none,
 				       /*require_all_args=*/true,
@@ -18001,6 +18356,13 @@ dependent_template_arg_p (tree arg)
   if (!processing_template_decl)
     return false;
 
+  /* Assume a template argument that was wrongly written by the user
+     is dependent. This is consistent with what
+     any_dependent_template_arguments_p [that calls this function]
+     does.  */
+  if (arg == error_mark_node)
+    return true;
+
   if (TREE_CODE (arg) == TEMPLATE_DECL
       || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
     return dependent_template_p (arg);
@@ -18428,7 +18790,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,
-     TYPE_NAME (au), NULL_TREE);
+     0, 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 b8f76b0..7e33693 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1062,22 +1062,6 @@ strip_typedefs (tree t)
   return cp_build_qualified_type (result, cp_type_quals (t));
 }
 
-/* Setup a TYPE_DECL node as a typedef representation.
-   See comments of set_underlying_type in c-common.c.  */
-
-void
-cp_set_underlying_type (tree t)
-{
-  set_underlying_type (t);
-  /* If T is a template type parm, make it require structural equality.
-     This is useful when comparing two template type parms,
-     because it forces the comparison of the template parameters of their
-     decls.  */
-  if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
-    SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
 /* 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/cp/typeck.c b/gcc/cp/typeck.c
index 160198b..76d6f12 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
 static bool
 comp_template_parms_position (tree t1, tree t2)
 {
+  tree index1, index2;
   gcc_assert (t1 && t2
 	      && TREE_CODE (t1) == TREE_CODE (t2)
 	      && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
 		  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
-      if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
-	  || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
-          || (TEMPLATE_TYPE_PARAMETER_PACK (t1) 
-              != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
-	return false;
-
-      return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
-   Return the template parameter of the dependent type T.
-   If T is a typedef, return the template parameters of
-   the _decl_ of the typedef. T must be a dependent type.  */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
-  tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
-  /* First, try the obvious case of getting the
-     template info from T itself.  */
-  if ((tinfo = get_template_info (t)))
-    ;
-  else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-    return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
-  else if (typedef_variant_p (t)
-	   && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
-    tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
-  /* If T is a TYPENAME_TYPE which context is a template type
-     parameter, get the template parameters from that context.  */
-  else if (TYPE_CONTEXT (t)
-	   && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
-   return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
-  else if (TYPE_CONTEXT (t)
-	   && !NAMESPACE_SCOPE_P (t))
-    tinfo = get_template_info (TYPE_CONTEXT (t));
-
-  if (tinfo)
-    tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
-  return tparms;
-}
-
-/* Subroutine of structural_comptypes.
-   Compare the dependent types T1 and T2.
-   Return TRUE if we are sure they can't be equal, FALSE otherwise.
-   The whole point of this function is to support cases where either T1 or
-   T2 is a typedef. In those cases, we need to compare the template parameters
-   of the _decl_ of the typedef. If those don't match then we know T1
-   and T2 cannot be equal.  */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
-  tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
-  bool t1_typedef_variant_p, t2_typedef_variant_p;
-
-  if (!uses_template_parms (t1) || !uses_template_parms (t2))
-    return false;
-
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
-    {
-      /* If T1 and T2 don't have the same relative position in their
-	 template parameters set, they can't be equal.  */
-      if (!comp_template_parms_position (t1, t2))
-	return true;
-    }
-
-  t1_typedef_variant_p = typedef_variant_p (t1);
-  t2_typedef_variant_p = typedef_variant_p (t2);
+  index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
+  index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
 
-  /* Either T1 or T2 must be a typedef.  */
-  if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+  /* 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;
 
-  if (!t1_typedef_variant_p || !t2_typedef_variant_p)
-    /* Either T1 or T2 is not a typedef so we cannot compare the
-       template parms of the typedefs of T1 and T2.
-       At this point, if the main variant type of T1 and T2 are equal
-       it means the two types can't be incompatible, from the perspective
-       of this function.  */
-    if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-      return false;
-
-  /* So if we reach this point, it means either T1 or T2 is a typedef variant.
-     Let's compare their template parameters.  */
-
-  tparms1 = get_template_parms_of_dependent_type (t1);
-  tparms2 = get_template_parms_of_dependent_type (t2);
-
-  /* If T2 is a template type parm and if we could not get the template
-     parms it belongs to, that means we have not finished parsing the
-     full set of template parameters of the template declaration it
-     belongs to yet. If we could get the template parms T1 belongs to,
-     that mostly means T1 and T2 belongs to templates that are
-     different and incompatible.  */
-  if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
-      && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
-      && tparms1 != tparms2)
-    return true;
-
-  if (tparms1 == NULL_TREE
-      || tparms2 == NULL_TREE
-      || tparms1 == tparms2)
+  /* Then compare their relative position.  */
+  if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
+      || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
+      || (TEMPLATE_PARM_PARAMETER_PACK (index1)
+	  != TEMPLATE_PARM_PARAMETER_PACK (index2)))
     return false;
 
-  /* And now compare the mighty template parms!  */
-  return !comp_template_parms (tparms1, tparms2);
+  return true;
 }
 
 /* Subroutine in comptypes.  */
@@ -1301,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict)
   if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
     return false;
 
-  /* If T1 and T2 are dependent typedefs then check upfront that
-     the template parameters of their typedef DECLs match before
-     going down checking their subtypes.  */
-  if (incompatible_dependent_types_p (t1, t2))
-    return false;
-
   /* Allow for two different type nodes which have essentially the same
      definition.  Note that we already checked for equality of the type
      qualifiers (just above).  */
@@ -1407,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      /* If incompatible_dependent_types_p called earlier didn't decide
-         T1 and T2 were different, they might be equal.  */
+      /* If T1 and T2 don't have the same relative position in their
+	 template parameters set, they can't be equal.  */
+      if (!comp_template_parms_position (t1, t2))
+	return false;
       break;
 
     case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/canon-type-10.C b/gcc/testsuite/g++.dg/template/canon-type-10.C
new file mode 100644
index 0000000..0c38946
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-10.C
@@ -0,0 +1,23 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U = TT<int, C> >
+struct S
+{
+  void foo(TT<T, C>);
+};
+
+template<class T,
+	 template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+	 class U>
+void
+S<T, TT, U>::foo(TT<T, C>)
+{
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-11.C b/gcc/testsuite/g++.dg/template/canon-type-11.C
new file mode 100644
index 0000000..698fe31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-11.C
@@ -0,0 +1,39 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+  void bar();
+};
+
+template<class T>
+void
+C<T>::bar()
+{
+}
+
+
+template<class U,
+	 template<class TT0_T0> class TT0 = C,
+	 template<class TT1_T0> class TT1 = TT0>
+struct S
+{
+  C<U> s;
+
+  void foo(TT1<U>);
+
+  void bar()
+  {
+    foo(s);
+  }
+};
+
+template<class T,
+	 template<class TT0_T0> class TT0,
+	 template<class TT1_T0> class TT1>
+void
+S<T, TT0, TT1>::foo(TT1<T>)
+{
+  C<T> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-12.C b/gcc/testsuite/g++.dg/template/canon-type-12.C
new file mode 100644
index 0000000..694cc5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-12.C
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+
+template<class T, T t = (T)0>
+struct S
+{
+  void
+  foo(decltype(t) = t);
+};
+
+template<class T, T t>
+void
+S<T, t>::foo(T)
+{
+}
+
+void
+bar()
+{
+  S<int> s;
+  s.foo();
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-13.C b/gcc/testsuite/g++.dg/template/canon-type-13.C
new file mode 100644
index 0000000..ca39cea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-13.C
@@ -0,0 +1,27 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct S0
+{
+};
+
+template<class T>
+struct S1
+{
+};
+
+template<class T, template<class T>  class A, template<class T>  class B = A>
+struct C
+{
+  B<T> m;
+};
+
+void
+foo()
+{
+  C<int, S0> s;
+  S0<int> s0;
+
+  s.m = s0;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-9.C b/gcc/testsuite/g++.dg/template/canon-type-9.C
new file mode 100644
index 0000000..de6170e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-9.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-options "-std=c++0x" }
+// { dg-do "compile" }
+
+struct F { F(int) {}};
+
+template<class T, T* u>
+struct S
+{
+  decltype(u) foo(T);
+};
+
+template<class T, T *u>
+T* S<T, u>::foo(T)
+{
+  T t;
+  return t;
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..318deef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+template<class T, class U = int>
+struct S0
+{
+  typedef int const_iterator;
+};
+
+template<class T>
+struct Test
+{
+  typedef S0<T> SAlias;
+  typedef typename SAlias::const_iterator const_iterator;
+  const_iterator begin ();
+};
+
+template<class T>
+typename S0<T>::const_iterator
+Test<T>::begin()
+{
+  return 0;
+}

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-27 15:59                                                         ` Dodji Seketeli
@ 2010-10-28 17:54                                                           ` Jason Merrill
  2010-12-17 20:51                                                           ` H.J. Lu
  1 sibling, 0 replies; 38+ messages in thread
From: Jason Merrill @ 2010-10-28 17:54 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

Looks good.

Jason

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-10-27 15:59                                                         ` Dodji Seketeli
  2010-10-28 17:54                                                           ` Jason Merrill
@ 2010-12-17 20:51                                                           ` H.J. Lu
  2011-10-28 21:47                                                             ` H.J. Lu
  1 sibling, 1 reply; 38+ messages in thread
From: H.J. Lu @ 2010-12-17 20:51 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Jason Merrill, GCC Patches

On Wed, Oct 27, 2010 at 7:24 AM, Dodji Seketeli <dodji@redhat.com> wrote:
> Hello,
>
> So I forgot to remove the wrong "optimization" on the parms of
> template template parameters. In the patch at the end of this message
> this hunks fixes that:
>
...
>
> Below is the fully updated patch. Fully bootstrapped and tested on
> x86_64-unknown-linux-gnu.
>
> --
>        Dodji
>
> commit c21c5f024f47a9a55facbd70c0d1f36956cff7c4
> Author: Dodji Seketeli <dodji@redhat.com>
> Date:   Mon Sep 13 12:12:21 2010 +0200
>
>    Restore canonical type comparison for dependent typedefs
>
>    gcc/cp/ChangeLog:
>        PR c++/45606
>        * cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
>        (struct template_parm_index_s)<num_siblings>: New field.
>        (TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
>        (process_template_parm): Extend the API to accept the number of
>        template parms in argument.
>        (cp_set_underlying_type): Remove this.
>        * class.c (build_self_reference): Require canonical type equality
>        back on the self reference of class.
>        * decl2.c (grokfield): Require canonical type equality back on
>        typedef class fields.
>        * name-lookup.c (pushdecl_maybe_friend): Require canonical type
>        equality back on typedefs.
>        * parser.c (cp_parser_template_parameter_list): Do not require
>        canonical type equality on dependent types created during
>        template parameters parsing.
>        * pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
>        (fixup_template_parm, fixup_template_parms): New private
>        functions.
>        (current_template_args): Declare this.
>        (process_template_parm): Pass the total number of template parms
>        to canonical_type_parameter.
>        (build_template_parm_index): Add a new argument to carry the total
>        number of template parms.
>        (reduce_template_parm_level, process_template_parm, make_auto): Adjust.
>        (current_template_args): Fix this for template template
>        parameters.
>        (tsubst_template_parm): Split out of ...
>        (tsubst_template_parms): ... this.
>        (reduce_template_parm_level): Don't loose
>        TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
>        (template_parm_to_arg): Extracted this function from
>        current_template_args. Make it represent invalid template parms
>        with an error_mark_node instead of a LIST_TREE containing an
>        error_mark_node.
>        (current_template_args): Use template_parm_to_arg.
>        (dependent_template_arg_p): Consider an invalid template argument
>        as dependent.
>        (end_template_parm_list): Do not update template sibling parms
>        here anymore. Use fixup_template_parms instead.
>        (process_template_parm): Pass the number of template parms to
>        canonical_type_parameter.
>        (make_auto): Require structural equality on auto
>        TEMPLATE_TYPE_PARM for now.
>        (unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
>        using all the arguments deduced so far.
>        (tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
>        canonical_type_parameter.
>        * tree.c (cp_set_underlying_type): Remove.
>        * typeck.c (get_template_parms_of_dependent_type)
>        (incompatible_dependent_types_p): Remove.
>        (structural_comptypes): Do not call incompatible_dependent_types_p
>        anymore.
>        (comp_template_parms_position): Re-organized. Take the length of
>        template parms list in account.
>
>    gcc/testsuite/ChangeLog:
>        PR c++/45606
>        * g++.dg/template/typedef36.C: New test.
>        * gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
>        * g++.dg/template/canon-type-10.C: Likewise.
>        * g++.dg/template/canon-type-11.C: Likewise.
>        * g++.dg/template/canon-type-12.C: Likewise.
>        * g++.dg/template/canon-type-13.C: Likewise.
>


This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46394


-- 
H.J.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: Require canonical type comparison for typedefs again.
  2010-12-17 20:51                                                           ` H.J. Lu
@ 2011-10-28 21:47                                                             ` H.J. Lu
  0 siblings, 0 replies; 38+ messages in thread
From: H.J. Lu @ 2011-10-28 21:47 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Jason Merrill, GCC Patches

On Fri, Dec 17, 2010 at 12:11 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Wed, Oct 27, 2010 at 7:24 AM, Dodji Seketeli <dodji@redhat.com> wrote:
>> Hello,
>>
>> So I forgot to remove the wrong "optimization" on the parms of
>> template template parameters. In the patch at the end of this message
>> this hunks fixes that:
>>
> ...
>>
>> Below is the fully updated patch. Fully bootstrapped and tested on
>> x86_64-unknown-linux-gnu.
>>
>> --
>>        Dodji
>>
>> commit c21c5f024f47a9a55facbd70c0d1f36956cff7c4
>> Author: Dodji Seketeli <dodji@redhat.com>
>> Date:   Mon Sep 13 12:12:21 2010 +0200
>>
>>    Restore canonical type comparison for dependent typedefs
>>
>>    gcc/cp/ChangeLog:
>>        PR c++/45606
>>        * cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
>>        (struct template_parm_index_s)<num_siblings>: New field.
>>        (TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
>>        (process_template_parm): Extend the API to accept the number of
>>        template parms in argument.
>>        (cp_set_underlying_type): Remove this.
>>        * class.c (build_self_reference): Require canonical type equality
>>        back on the self reference of class.
>>        * decl2.c (grokfield): Require canonical type equality back on
>>        typedef class fields.
>>        * name-lookup.c (pushdecl_maybe_friend): Require canonical type
>>        equality back on typedefs.
>>        * parser.c (cp_parser_template_parameter_list): Do not require
>>        canonical type equality on dependent types created during
>>        template parameters parsing.
>>        * pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
>>        (fixup_template_parm, fixup_template_parms): New private
>>        functions.
>>        (current_template_args): Declare this.
>>        (process_template_parm): Pass the total number of template parms
>>        to canonical_type_parameter.
>>        (build_template_parm_index): Add a new argument to carry the total
>>        number of template parms.
>>        (reduce_template_parm_level, process_template_parm, make_auto): Adjust.
>>        (current_template_args): Fix this for template template
>>        parameters.
>>        (tsubst_template_parm): Split out of ...
>>        (tsubst_template_parms): ... this.
>>        (reduce_template_parm_level): Don't loose
>>        TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
>>        (template_parm_to_arg): Extracted this function from
>>        current_template_args. Make it represent invalid template parms
>>        with an error_mark_node instead of a LIST_TREE containing an
>>        error_mark_node.
>>        (current_template_args): Use template_parm_to_arg.
>>        (dependent_template_arg_p): Consider an invalid template argument
>>        as dependent.
>>        (end_template_parm_list): Do not update template sibling parms
>>        here anymore. Use fixup_template_parms instead.
>>        (process_template_parm): Pass the number of template parms to
>>        canonical_type_parameter.
>>        (make_auto): Require structural equality on auto
>>        TEMPLATE_TYPE_PARM for now.
>>        (unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
>>        using all the arguments deduced so far.
>>        (tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
>>        canonical_type_parameter.
>>        * tree.c (cp_set_underlying_type): Remove.
>>        * typeck.c (get_template_parms_of_dependent_type)
>>        (incompatible_dependent_types_p): Remove.
>>        (structural_comptypes): Do not call incompatible_dependent_types_p
>>        anymore.
>>        (comp_template_parms_position): Re-organized. Take the length of
>>        template parms list in account.
>>
>>    gcc/testsuite/ChangeLog:
>>        PR c++/45606
>>        * g++.dg/template/typedef36.C: New test.
>>        * gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
>>        * g++.dg/template/canon-type-10.C: Likewise.
>>        * g++.dg/template/canon-type-11.C: Likewise.
>>        * g++.dg/template/canon-type-12.C: Likewise.
>>        * g++.dg/template/canon-type-13.C: Likewise.
>>
>
>
> This caused:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46394
>

It also caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50870

-- 
H.J.

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2011-10-28 19:44 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-11 18:30 [Dodji Seketeli] Patch PR c++/45200 Dodji Seketeli
2010-08-11 21:04 ` Jason Merrill
2010-08-11 21:06   ` Andrew Pinski
2010-08-12 13:20   ` Dodji Seketeli
2010-08-12 14:35     ` Jason Merrill
2010-08-13 10:30       ` Dodji Seketeli
2010-08-13 15:09         ` Jason Merrill
2010-09-19 22:34       ` Require canonical type comparison for typedefs again. (was Patch PR c++/45200) Dodji Seketeli
2010-09-19 22:47         ` Paolo Carlini
2010-09-20 10:28           ` Require canonical type comparison for typedefs again Dodji Seketeli
2010-09-20 15:35             ` H.J. Lu
2010-09-20 17:07               ` Dodji Seketeli
2010-09-20 21:44                 ` Jason Merrill
2010-09-26 14:44                   ` Dodji Seketeli
2010-09-26 15:10                     ` Jason Merrill
2010-09-28 15:12                       ` Dodji Seketeli
2010-09-28 15:15                         ` Dodji Seketeli
2010-09-28 16:51                         ` Jason Merrill
2010-09-30  8:55                           ` Dodji Seketeli
2010-09-30  9:10                             ` Jason Merrill
2010-10-06 18:53                               ` Dodji Seketeli
2010-10-06 22:15                                 ` Paolo Carlini
2010-10-15 16:09                                   ` Dodji Seketeli
2010-10-20 15:43                                     ` Jason Merrill
2010-10-20 21:10                                       ` Dodji Seketeli
2010-10-20 21:21                                         ` Jason Merrill
2010-10-20 22:06                                           ` Dodji Seketeli
2010-10-21  1:06                                             ` Jason Merrill
2010-10-23 22:46                                               ` Dodji Seketeli
2010-10-23 23:39                                                 ` Jason Merrill
2010-10-24  2:33                                                   ` Dodji Seketeli
2010-10-24  3:03                                                     ` Jason Merrill
2010-10-25 11:52                                                       ` Dodji Seketeli
2010-10-27 15:59                                                         ` Dodji Seketeli
2010-10-28 17:54                                                           ` Jason Merrill
2010-12-17 20:51                                                           ` H.J. Lu
2011-10-28 21:47                                                             ` H.J. Lu
2010-10-07 18:30                                 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).