This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] PR c++/50852 - loose template parameter comparison


> How about if we just store a pointer to the template parameter list
> and do comp_template_parms?

I tried a variation of this approach below.  My understanding is that
comp_template_parms wouldn't work as is, at least because it can lead to
an endless recursion:

Suppose we start comparing the first template parm P of a vector V of
parameters against another template parm P'.  We compare the kind,
level and position of P and P'.  Then we move on to comparing their
siblings, via comp_template_parms.  That will, at some point compare,
P and P' again.

So I have added a new COMPARE_NO_SIBLINGS flag to the other COMPARE_*
flag that are passed as a last argument (named STRICT) to
structural_comptypes and comptypes, to prevent that endless recursion.

A drawback with this is that all the comparisons that happen from
inside structural_comptypes must take the STRICT parameter to avoid
that recursion.  This makes quite a lot of changes, even if they are
almost mechanical.  I tried to think of a better way to handle this,
but alas.

Also, it occurred that storing a pointer to the full template
parameter list was not really appropriate e.g for cases where tsubst
reduces the level of a given template parameter.  A pointer to just
the innermost vector of siblings of the template parameter was enough.
I thus extracted a comp_template_parm_levels to compare just a level
(a vector) of template parameters against another one.

As for the possible performance regression, I couldn't notice any
slowdown in in full bootstrap time, or in compiling some local
templated c++ code here.

Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.

gcc/cp/

	PR c++/50852
	* cp-tree.h (struct template_parm_index_s)<num_siblings>: Remove.
	(struct template_parm_index_s)<siblings>: New member.
	(TEMPLATE_PARM_SIBLINGS): New accessor macro.
	(process_template_parm): Change the integer num_siblings parm into
	a tree siblings parm.
	(comp_template_parms_siblings, comp_template_parm_levels)
	(comp_template_parms_real, comp_template_args_real)
	(same_type_ignoring_top_level_qualifiers_real_p): Declare new
	functions.
	(compare_trees): Declare new function.
	* pt.c (build_template_parm_index, fixup_template_type_parm_type)
	(fixup_template_parm_index, build_template_parm_index)
	(fixup_template_parm_index, process_template_parm)
	(fixup_template_type_parm_type, fixup_template_parm): Change the
	integer num_siblings parm into a tree siblings parm.  Update
	comments.
	(comp_template_parm_levels): Define new function.
	(comp_template_parms_real): Take an additional parm to control
	comparison.  Factorize this out of ...
	(comp_template_parms): ... this.
	(reduce_template_parm_level): Use TEMPLATE_PARM_SIBLINGS instead
	of TEMPLATE_PARM_NUM_SIBLINGS.
	(template_args_equal_real): Take an additional parm to control
	comparison.  Use template_args_equal_real instead of
	template_args_equal.  Factorize this out of ...
	(template_args_equal): ... this.
	(comp_template_args_real): Take an additional parm to control
	comparison.  Renamed from comp_template_args_with_info.  Make this
	public.
	(comp_template_args, unify_pack_expansion): Adjust.
	* tree.c (compare_trees): Factorized this out of cp_tree_equal.
	Take a comparison control parameter. Use tree comparison functions
	that take a comparison control parm.
	(cp_tree_equal): Use the factorized compare_trees.
	* typeck.c (compparms_real): Take a comparison control parameter.
	Split out of ...
	(compparms): ... this.
	(comp_template_parms_siblings): Define new function.
	(comp_template_parms_position): Take an additional parameter to
	control the comparison.  Use the new comp_template_parms_siblings.
	(structural_comptypes): Use type comparison routines variants that
	take the comparison control parm.
	(same_type_ignoring_top_level_qualifiers_real_p): Take an
	additional parm to control comparison.  USe comptypes instead of
	comptypes.  Factorize out of ...
	(same_type_ignoring_top_level_qualifiers_p): ... this.

gcc/testsuite/

	PR c++/50852
	* g++.dg/template/typedef39.C: New test.
	* g++.dg/template/typedef40.C: Likewise.
	* g++.dg/template/typedef41.C: Likewise.
---
 gcc/cp/cp-tree.h                          |   25 +++-
 gcc/cp/pt.c                               |  226 ++++++++++++++++++-----------
 gcc/cp/tree.c                             |  113 +++++++++------
 gcc/cp/typeck.c                           |  174 +++++++++++++++++------
 gcc/testsuite/g++.dg/template/typedef39.C |   16 ++
 gcc/testsuite/g++.dg/template/typedef40.C |   22 +++
 gcc/testsuite/g++.dg/template/typedef41.C |   19 +++
 7 files changed, 416 insertions(+), 179 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/typedef39.C
 create mode 100644 gcc/testsuite/g++.dg/template/typedef40.C
 create mode 100644 gcc/testsuite/g++.dg/template/typedef41.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ccad644..e2c36a1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -246,7 +246,9 @@ struct GTY(()) template_parm_index_s {
   int index;
   int level;
   int orig_level;
-  int num_siblings;
+  /* A TREE_VEC containing the set of parms this parameter belongs
+     to. */
+  tree siblings;
   tree decl;
 };
 typedef struct template_parm_index_s template_parm_index;
@@ -4471,6 +4473,9 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
 				   structural. The actual comparison
 				   will be identical to
 				   COMPARE_STRICT.  */
+#define COMPARE_NO_SIBLINGS   16 /* When comparing template
+				    parameters, don't consider their
+				    siblings.  */
 
 /* Used with push_overloaded_decl.  */
 #define PUSH_GLOBAL	     0  /* Push the DECL into namespace scope,
@@ -4504,9 +4509,10 @@ 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)
+/* A TREE_VEC containing the sibling parameters for a given template
+   parm.  */
+#define TEMPLATE_PARM_SIBLINGS(NODE) \
+  (TEMPLATE_PARM_INDEX_CAST (NODE)->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)
@@ -5275,7 +5281,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, unsigned);
+						 bool, bool, tree);
 extern tree end_template_parm_list		(tree);
 void fixup_template_parms (void);
 extern void end_template_decl			(void);
@@ -5302,6 +5308,9 @@ extern void do_type_instantiation		(tree, tree, tsubst_flags_t);
 extern bool always_instantiate_p		(tree);
 extern void maybe_instantiate_noexcept		(tree);
 extern tree instantiate_decl			(tree, int, bool);
+extern bool comp_template_parms_siblings        (tree, tree, int);
+extern int comp_template_parm_levels            (const_tree, const_tree, int);
+extern int comp_template_parms_real		(const_tree, const_tree, int);
 extern int comp_template_parms			(const_tree, const_tree);
 extern bool uses_parameter_packs                (tree);
 extern bool template_parameter_pack_p           (const_tree);
@@ -5316,6 +5325,8 @@ extern int template_class_depth			(tree);
 extern int is_specialization_of			(tree, tree);
 extern bool is_specialization_of_friend		(tree, tree);
 extern tree get_pattern_parm			(tree, tree);
+extern int comp_template_args_real              (tree, tree, tree *,
+						 tree *, int);
 extern int comp_template_args			(tree, tree);
 extern tree maybe_process_partial_specialization (tree);
 extern tree most_specialized_instantiation	(tree);
@@ -5694,6 +5705,7 @@ extern tree lvalue_type				(tree);
 extern tree error_type				(tree);
 extern int varargs_function_p			(const_tree);
 extern bool really_overloaded_fn		(tree);
+extern bool compare_trees                       (tree, tree, int);
 extern bool cp_tree_equal			(tree, tree);
 extern tree no_linkage_check			(tree, bool);
 extern void debug_binfo				(tree);
@@ -5754,6 +5766,9 @@ extern int type_unknown_p			(const_tree);
 enum { ce_derived, ce_normal, ce_exact };
 extern bool comp_except_specs			(const_tree, const_tree, int);
 extern bool comptypes				(tree, tree, int);
+extern bool same_type_ignoring_top_level_qualifiers_real_p (tree type1,
+							    tree type2,
+							    int strict);
 extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree);
 extern bool compparms				(const_tree, const_tree);
 extern int comp_cv_qualification		(const_tree, const_tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a4460f1..a71b45e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -148,7 +148,7 @@ static tree convert_template_argument (tree, tree, tree,
 static int for_each_template_parm (tree, tree_fn_t, void*,
 				   struct pointer_set_t*, bool);
 static tree expand_template_argument_pack (tree);
-static tree build_template_parm_index (int, int, int, int, tree, tree);
+static tree build_template_parm_index (int, int, int, tree, tree, tree);
 static bool inline_needs_template_parms (tree);
 static void push_inline_template_parms_recursive (tree, int);
 static tree retrieve_local_specialization (tree);
@@ -183,6 +183,7 @@ static tree try_class_unification (tree, tree, tree, tree, bool);
 static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
 					   tree, tree);
 static bool template_template_parm_bindings_ok_p (tree, tree);
+static int template_args_equal_real (tree, tree, int);
 static int template_args_equal (tree, tree);
 static void tsubst_default_arguments (tree);
 static tree for_each_template_parm_r (tree *, int *, void *);
@@ -205,8 +206,8 @@ static tree listify_autos (tree, tree);
 static tree template_parm_to_arg (tree t);
 static bool arg_from_parm_pack_p (tree, tree);
 static tree current_template_args (void);
-static tree fixup_template_type_parm_type (tree, int);
-static tree fixup_template_parm_index (tree, tree, int);
+static tree fixup_template_type_parm_type (tree, tree);
+static tree fixup_template_parm_index (tree, tree, tree);
 static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
@@ -2696,11 +2697,56 @@ check_explicit_specialization (tree declarator,
 }
 
 /* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
+   parameters of a given level, represented by a TREE_VEC of
+   TREE_LIST.  The TREE_VALUE of each TREE_LIST represents a given
+   template parameter.  STRICT controls how the comparison is done.
+   It has the same meaning as the last parameter of the comptypes
+   function.  */
+
+int
+comp_template_parm_levels (const_tree parms_level1,
+			   const_tree parms_level2,
+			   int strict)
+{
+  int i;
+  gcc_assert (TREE_CODE (parms_level1) == TREE_VEC);
+  gcc_assert (TREE_CODE (parms_level2) == TREE_VEC);
+
+  if (TREE_VEC_LENGTH (parms_level1) != TREE_VEC_LENGTH (parms_level2))
+    return 0;
+
+  for (i = 0; i < TREE_VEC_LENGTH (parms_level2); ++i)
+    {
+      tree parm1 = TREE_VALUE (TREE_VEC_ELT (parms_level1, i));
+      tree parm2 = TREE_VALUE (TREE_VEC_ELT (parms_level2, i));
+
+      /* If either of the template parameters are invalid, assume
+	 they match for the sake of error recovery. */
+      if (parm1 == error_mark_node || parm2 == error_mark_node)
+	return 1;
+
+      if (TREE_CODE (parm1) != TREE_CODE (parm2))
+	return 0;
+
+      if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM
+	  && (TEMPLATE_TYPE_PARAMETER_PACK (parm1)
+	      == TEMPLATE_TYPE_PARAMETER_PACK (parm2)))
+	continue;
+      else if (!comptypes (TREE_TYPE (parm1), TREE_TYPE (parm2), strict))
+	return 0;
+    }
+  return 1;
+}
+
+/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
    parameters.  These are represented in the same format used for
-   DECL_TEMPLATE_PARMS.  */
+   DECL_TEMPLATE_PARMS.  STRICT controls how the comparison is done.
+   Its semantics are the same as the last parameter of comptypes.  */
 
 int
-comp_template_parms (const_tree parms1, const_tree parms2)
+comp_template_parms_real (const_tree parms1,
+			  const_tree parms2,
+			  int strict)
 {
   const_tree p1;
   const_tree p2;
@@ -2714,37 +2760,20 @@ comp_template_parms (const_tree parms1, const_tree parms2)
     {
       tree t1 = TREE_VALUE (p1);
       tree t2 = TREE_VALUE (p2);
-      int i;
 
-      gcc_assert (TREE_CODE (t1) == TREE_VEC);
-      gcc_assert (TREE_CODE (t2) == TREE_VEC);
-
-      if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
+      if (!comp_template_parm_levels (t1, t2, strict))
 	return 0;
-
-      for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
-	{
-          tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
-          tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
-
-          /* If either of the template parameters are invalid, assume
-             they match for the sake of error recovery. */
-          if (parm1 == error_mark_node || parm2 == error_mark_node)
-            return 1;
-
-	  if (TREE_CODE (parm1) != TREE_CODE (parm2))
-	    return 0;
-
-	  if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM
-              && (TEMPLATE_TYPE_PARAMETER_PACK (parm1)
-                  == TEMPLATE_TYPE_PARAMETER_PACK (parm2)))
-	    continue;
-	  else if (!same_type_p (TREE_TYPE (parm1), TREE_TYPE (parm2)))
-	    return 0;
-	}
     }
 
-  if ((p1 != NULL_TREE) != (p2 != NULL_TREE))
+  /*  Don't compare depths template parms levels when we are in the
+      process of comparing siblings of a given template parm.  This is
+      because the TEMPLATE_PARM_SIBLINGS property of a template parm
+      which level has been reduced by tsubst still points to the
+      original siblings, which level is greater; while comparing those
+      siblings with another set of siblings, considering their depths
+      can lead to errors.  */
+  if (!(strict & COMPARE_NO_SIBLINGS)
+      && (p1 != NULL_TREE) != (p2 != NULL_TREE))
     /* One set of parameters has more parameters lists than the
        other.  */
     return 0;
@@ -2752,6 +2781,17 @@ comp_template_parms (const_tree parms1, const_tree parms2)
   return 1;
 }
 
+/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
+   parameters.  These are represented in the same format used for
+   DECL_TEMPLATE_PARMS.  */
+
+int
+comp_template_parms (const_tree parms1, const_tree parms2)
+{
+  return comp_template_parms_real (parms1, parms2,
+				   COMPARE_STRICT);
+}
+
 /* Determine whether PARM is a parameter pack.  */
 
 bool 
@@ -3414,14 +3454,14 @@ check_template_shadow (tree decl)
 }
 
 /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
-   ORIG_LEVEL, DECL, and TYPE.  NUM_SIBLINGS is the total number of
-   template parameters.  */
+   ORIG_LEVEL, DECL, and TYPE.  SIBLINGS is a TREE_VEC containing the
+   set of parameters the current template parameter belongs to.  */
 
 static tree
 build_template_parm_index (int index,
 			   int level,
 			   int orig_level,
-			   int num_siblings,
+			   tree siblings,
 			   tree decl,
 			   tree type)
 {
@@ -3429,7 +3469,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_SIBLINGS (t) = siblings;
   TEMPLATE_PARM_DECL (t) = decl;
   TREE_TYPE (t) = type;
   TREE_CONSTANT (t) = TREE_CONSTANT (decl);
@@ -3495,7 +3535,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),
+				     TEMPLATE_PARM_SIBLINGS (index),
 				     decl, type);
       TEMPLATE_PARM_DESCENDANTS (index) = t;
       TEMPLATE_PARM_PARAMETER_PACK (t) 
@@ -3515,16 +3555,16 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
    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
+   is in PARM_LOC.  SIBLING_PARMS is a TREE_VEC containing the set of
+   template parameters 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.  */
+   iff PARM is a type.  If the set of parameters is not known, this
+   parameter shall be set to NULL_TREE.  */
 
 tree
 process_template_parm (tree list, location_t parm_loc, tree parm,
 		       bool is_non_type, bool is_parameter_pack,
-		       unsigned num_template_parms)
+		       tree sibling_parms)
 {
   tree decl = 0;
   tree defval;
@@ -3599,7 +3639,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
       DECL_INITIAL (parm) = DECL_INITIAL (decl)
 	= build_template_parm_index (idx, processing_template_decl,
 				     processing_template_decl,
-				     num_template_parms,
+				     sibling_parms,
 				     decl, TREE_TYPE (parm));
 
       TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)) 
@@ -3633,7 +3673,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
       TEMPLATE_TYPE_PARM_INDEX (t)
 	= build_template_parm_index (idx, processing_template_decl,
 				     processing_template_decl,
-				     num_template_parms,
+				     sibling_parms,
 				     decl, TREE_TYPE (parm));
       TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
       TYPE_CANONICAL (t) = canonical_type_parameter (t);
@@ -3676,21 +3716,21 @@ end_template_parm_list (tree parms)
 /* 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.
+     1/ T has a new TEMPLATE_PARM_INDEX that carries the set of
+     sibling template parameters of T.
 
-     2/ T has a new canonical type that matches the new number
-     of sibling parms.
+     2/ T has a new canonical type that matches the set 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.
+     name of TYPE will return.  No lookup should return TYPE anymore.
 
-   NUM_PARMS is the new number of sibling parms TYPE belongs to.
+   SIBLING_PARMS is the set 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)
+fixup_template_type_parm_type (tree type, tree sibling_parms)
 {
   tree orig_idx = TEMPLATE_TYPE_PARM_INDEX (type), idx;
   tree t;
@@ -3700,7 +3740,7 @@ fixup_template_type_parm_type (tree type, int num_parms)
   tree decl;
 
   /* Do not fix up the type twice.  */
-  if (orig_idx && TEMPLATE_PARM_NUM_SIBLINGS (orig_idx) != 0)
+  if (orig_idx && TEMPLATE_PARM_SIBLINGS (orig_idx) != NULL_TREE)
     return type;
 
   t = copy_type (type);
@@ -3714,7 +3754,7 @@ fixup_template_type_parm_type (tree type, int num_parms)
   idx = build_template_parm_index (TEMPLATE_PARM_IDX (orig_idx),
 				   TEMPLATE_PARM_LEVEL (orig_idx),
 				   TEMPLATE_PARM_ORIG_LEVEL (orig_idx),
-				   num_parms,
+				   sibling_parms,
 				   decl, t);
   TEMPLATE_PARM_DESCENDANTS (idx) = TEMPLATE_PARM_DESCENDANTS (orig_idx);
   TEMPLATE_PARM_PARAMETER_PACK (idx) = TEMPLATE_PARM_PARAMETER_PACK (orig_idx);
@@ -3738,26 +3778,26 @@ fixup_template_type_parm_type (tree type, int num_parms)
 /* 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
+   1/ carry the set of sibling parms (SIBLING_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
+   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)
+fixup_template_parm_index (tree i, tree args, tree sibling_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))
+      || (TEMPLATE_PARM_SIBLINGS (i) != NULL_TREE))
     return i;
 
   decl = TEMPLATE_PARM_DECL (i);
@@ -3766,7 +3806,7 @@ fixup_template_parm_index (tree i, tree args, int num_parms)
   index = build_template_parm_index (TEMPLATE_PARM_IDX (i),
 				     TEMPLATE_PARM_LEVEL (i),
 				     TEMPLATE_PARM_ORIG_LEVEL (i),
-				     num_parms,
+				     sibling_parms,
 				     decl, type);
 
   TEMPLATE_PARM_DESCENDANTS (index) = TEMPLATE_PARM_DESCENDANTS (i);
@@ -3789,8 +3829,8 @@ fixup_template_parm_index (tree i, tree args, int num_parms)
    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
+   the template parameter, starting at 0. SIBLING_PARMS is the set of
+   template parameters the 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
@@ -3801,7 +3841,7 @@ fixup_template_parm_index (tree i, tree args, int num_parms)
 static void
 fixup_template_parm (tree parm_desc,
 		     int idx,
-		     int num_parms,
+		     tree sibling_parms,
 		     tree arglist)
 {
   tree parm = TREE_VALUE (parm_desc);
@@ -3817,7 +3857,7 @@ fixup_template_parm (tree parm_desc,
 	 template parms into the default argument of this
 	 parameter.  */
       tree t =
-	fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
+	fixup_template_type_parm_type (TREE_TYPE (parm), sibling_parms);
       TREE_TYPE (parm) = t;
 
       TREE_VEC_ELT (fixedup_args, idx) = template_parm_to_arg (parm_desc);
@@ -3871,13 +3911,12 @@ fixup_template_parm (tree parm_desc,
 	    template_parm_to_arg (parameter);
 
 	  fixup_template_parm (parameter, j,
-			       TREE_VEC_LENGTH (tparms),
-			       targs);
+			       tparms, targs);
 	}
 
       /* Now fix up the type of the template template parm.  */
 
-      t = fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
+      t = fixup_template_type_parm_type (TREE_TYPE (parm), sibling_parms);
       TREE_TYPE (parm) = t;
 
       TREE_VEC_ELT (fixedup_args, idx) =
@@ -3917,7 +3956,7 @@ fixup_template_parm (tree parm_desc,
 	 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);
+	fixup_template_parm_index (index, arglist, sibling_parms);
 
       DECL_INITIAL (pushed_decl) = DECL_INITIAL (parm) = fixed_up_index;
 
@@ -3969,7 +4008,7 @@ fixup_template_parms (void)
   /* 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);
+			 i, parameter_vec, arglist);
 }
 
 /* end_template_decl is called after a template declaration is seen.  */
@@ -6928,10 +6967,12 @@ coerce_template_parms (tree parms,
   return new_inner_args;
 }
 
-/* Returns 1 if template args OT and NT are equivalent.  */
+/* Returns 1 if template args OT and NT are equivalent.  STRICT
+   controls how the comparison is done, with the same semantics as
+   for the last parameter of comptypes.  */
 
 static int
-template_args_equal (tree ot, tree nt)
+template_args_equal_real (tree ot, tree nt, int strict)
 {
   if (nt == ot)
     return 1;
@@ -6940,13 +6981,16 @@ template_args_equal (tree ot, tree nt)
 
   if (TREE_CODE (nt) == TREE_VEC)
     /* For member templates */
-    return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
+    return (TREE_CODE (ot) == TREE_VEC
+	    && comp_template_args_real (ot, nt, NULL, NULL, strict));
   else if (PACK_EXPANSION_P (ot))
     return (PACK_EXPANSION_P (nt)
-	    && template_args_equal (PACK_EXPANSION_PATTERN (ot),
-				    PACK_EXPANSION_PATTERN (nt))
-	    && template_args_equal (PACK_EXPANSION_EXTRA_ARGS (ot),
-				    PACK_EXPANSION_EXTRA_ARGS (nt)));
+	    && template_args_equal_real (PACK_EXPANSION_PATTERN (ot),
+					 PACK_EXPANSION_PATTERN (nt),
+					 strict)
+	    && template_args_equal_real (PACK_EXPANSION_EXTRA_ARGS (ot),
+					 PACK_EXPANSION_EXTRA_ARGS (nt),
+					 strict));
   else if (ARGUMENT_PACK_P (ot))
     {
       int i, len;
@@ -6961,8 +7005,9 @@ template_args_equal (tree ot, tree nt)
       if (TREE_VEC_LENGTH (npack) != len)
 	return 0;
       for (i = 0; i < len; ++i)
-	if (!template_args_equal (TREE_VEC_ELT (opack, i),
-				  TREE_VEC_ELT (npack, i)))
+	if (!template_args_equal_real (TREE_VEC_ELT (opack, i),
+				       TREE_VEC_ELT (npack, i),
+				       strict))
 	  return 0;
       return 1;
     }
@@ -6976,23 +7021,32 @@ template_args_equal (tree ot, tree nt)
       ot = ARGUMENT_PACK_SELECT_FROM_PACK (ot);
       if (nt && TREE_CODE (nt) == ARGUMENT_PACK_SELECT)
 	nt = ARGUMENT_PACK_SELECT_FROM_PACK (nt);
-      return template_args_equal (ot, nt);
+      return template_args_equal_real (ot, nt, strict);
     }
   else if (TYPE_P (nt))
-    return TYPE_P (ot) && same_type_p (ot, nt);
+    return TYPE_P (ot) && comptypes (ot, nt, strict);
   else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
     return 0;
   else
     return cp_tree_equal (ot, nt);
 }
 
+/* Returns 1 if template args OT and NT are equivalent.  */
+
+static int
+template_args_equal (tree ot, tree nt)
+{
+  return template_args_equal_real (ot, nt, COMPARE_STRICT);
+}
+
 /* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets of
    template arguments.  Returns 0 otherwise, and updates OLDARG_PTR and
    NEWARG_PTR with the offending arguments if they are non-NULL.  */
 
-static int
-comp_template_args_with_info (tree oldargs, tree newargs,
-			      tree *oldarg_ptr, tree *newarg_ptr)
+int
+comp_template_args_real (tree oldargs, tree newargs,
+			 tree *oldarg_ptr, tree *newarg_ptr,
+			 int strict)
 {
   int i;
 
@@ -7010,7 +7064,7 @@ comp_template_args_with_info (tree oldargs, tree newargs,
       tree nt = TREE_VEC_ELT (newargs, i);
       tree ot = TREE_VEC_ELT (oldargs, i);
 
-      if (! template_args_equal (ot, nt))
+      if (! template_args_equal_real (ot, nt, strict))
 	{
 	  if (oldarg_ptr != NULL)
 	    *oldarg_ptr = ot;
@@ -7028,7 +7082,8 @@ comp_template_args_with_info (tree oldargs, tree newargs,
 int
 comp_template_args (tree oldargs, tree newargs)
 {
-  return comp_template_args_with_info (oldargs, newargs, NULL, NULL);
+  return comp_template_args_real (oldargs, newargs,
+				  NULL, NULL, COMPARE_STRICT);
 }
 
 static void
@@ -16085,8 +16140,9 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
 	  tree bad_old_arg = NULL_TREE, bad_new_arg = NULL_TREE;
 	  tree old_args = ARGUMENT_PACK_ARGS (old_pack);
 
-	  if (!comp_template_args_with_info (old_args, new_args,
-					     &bad_old_arg, &bad_new_arg))
+	  if (!comp_template_args_real (old_args, new_args,
+					&bad_old_arg, &bad_new_arg,
+					COMPARE_STRICT))
 	    /* Inconsistent unification of this parameter pack.  */
 	    return unify_parameter_pack_inconsistent (explain_p,
 						      bad_old_arg,
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index bf8bc05..197df7d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2157,10 +2157,14 @@ decl_anon_ns_mem_p (const_tree decl)
 }
 
 /* Return truthvalue of whether T1 is the same tree structure as T2.
-   Return 1 if they are the same. Return 0 if they are different.  */
+   STRICT controls how the comparison is done, with the same semantics
+   as the for the last parameter of comptypes.  Please make sure that
+   any type or tree comparison function used in this function is a
+   variant that takes this STRICT parameter.  Return 1 if they are the
+   same. Return 0 if they are different.  */
 
 bool
-cp_tree_equal (tree t1, tree t2)
+compare_trees (tree t1, tree t2, int strict)
 {
   enum tree_code code1, code2;
 
@@ -2206,14 +2210,14 @@ cp_tree_equal (tree t1, tree t2)
 				     TREE_FIXED_CST (t2));
 
     case COMPLEX_CST:
-      return cp_tree_equal (TREE_REALPART (t1), TREE_REALPART (t2))
-	&& cp_tree_equal (TREE_IMAGPART (t1), TREE_IMAGPART (t2));
+      return compare_trees (TREE_REALPART (t1), TREE_REALPART (t2), strict)
+	&& compare_trees (TREE_IMAGPART (t1), TREE_IMAGPART (t2), strict);
 
     case CONSTRUCTOR:
       /* We need to do this when determining whether or not two
 	 non-type pointer to member function template arguments
 	 are the same.  */
-      if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+      if (!comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
 	  || CONSTRUCTOR_NELTS (t1) != CONSTRUCTOR_NELTS (t2))
 	return false;
       {
@@ -2222,22 +2226,22 @@ cp_tree_equal (tree t1, tree t2)
 	FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t1), i, field, value)
 	  {
 	    constructor_elt *elt2 = CONSTRUCTOR_ELT (t2, i);
-	    if (!cp_tree_equal (field, elt2->index)
-		|| !cp_tree_equal (value, elt2->value))
+	    if (!compare_trees (field, elt2->index, strict)
+		|| !compare_trees (value, elt2->value, strict))
 	      return false;
 	  }
       }
       return true;
 
     case TREE_LIST:
-      if (!cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
+      if (!compare_trees (TREE_PURPOSE (t1), TREE_PURPOSE (t2), strict))
 	return false;
-      if (!cp_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
+      if (!compare_trees (TREE_VALUE (t1), TREE_VALUE (t2), strict))
 	return false;
-      return cp_tree_equal (TREE_CHAIN (t1), TREE_CHAIN (t2));
+      return compare_trees (TREE_CHAIN (t1), TREE_CHAIN (t2), strict);
 
     case SAVE_EXPR:
-      return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+      return compare_trees (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), strict);
 
     case CALL_EXPR:
       {
@@ -2248,14 +2252,14 @@ cp_tree_equal (tree t1, tree t2)
 	tree name1 = dependent_name (CALL_EXPR_FN (t1));
 	tree name2 = dependent_name (CALL_EXPR_FN (t2));
 	if (!(name1 && name2 && name1 == name2)
-	    && !cp_tree_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
+	    && !compare_trees (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2), strict))
 	  return false;
 	for (arg1 = first_call_expr_arg (t1, &iter1),
 	       arg2 = first_call_expr_arg (t2, &iter2);
 	     arg1 && arg2;
 	     arg1 = next_call_expr_arg (&iter1),
 	       arg2 = next_call_expr_arg (&iter2))
-	  if (!cp_tree_equal (arg1, arg2))
+	  if (!compare_trees (arg1, arg2, strict))
 	    return false;
 	if (arg1 || arg2)
 	  return false;
@@ -2277,28 +2281,30 @@ cp_tree_equal (tree t1, tree t2)
 	else if (TREE_CODE (o2) == VAR_DECL && DECL_NAME (o2) == NULL_TREE
 		 && !DECL_RTL_SET_P (o2))
 	  /*Nop*/;
-	else if (!cp_tree_equal (o1, o2))
+	else if (!compare_trees (o1, o2, strict))
 	  return false;
 
-	return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+	return compare_trees (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1),
+			      strict);
       }
 
     case WITH_CLEANUP_EXPR:
-      if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+      if (!compare_trees (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), strict))
 	return false;
-      return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t1, 1));
+      return compare_trees (TREE_OPERAND (t1, 1), TREE_OPERAND (t1, 1), strict);
 
     case COMPONENT_REF:
       if (TREE_OPERAND (t1, 1) != TREE_OPERAND (t2, 1))
 	return false;
-      return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+      return compare_trees (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0),
+			    strict);
 
     case PARM_DECL:
       /* For comparing uses of parameters in late-specified return types
 	 with an out-of-class definition of the function, but can also come
 	 up for expressions that involve 'this' in a member function
 	 template.  */
-      if (same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+      if (comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
 	{
 	  if (DECL_ARTIFICIAL (t1) ^ DECL_ARTIFICIAL (t2))
 	    return false;
@@ -2321,26 +2327,25 @@ cp_tree_equal (tree t1, tree t2)
       return (BASELINK_BINFO (t1) == BASELINK_BINFO (t2)
 	      && BASELINK_ACCESS_BINFO (t1) == BASELINK_ACCESS_BINFO (t2)
 	      && BASELINK_QUALIFIED_P (t1) == BASELINK_QUALIFIED_P (t2)
-	      && cp_tree_equal (BASELINK_FUNCTIONS (t1),
-				BASELINK_FUNCTIONS (t2)));
+	      && compare_trees (BASELINK_FUNCTIONS (t1),
+				BASELINK_FUNCTIONS (t2), strict));
 
     case TEMPLATE_PARM_INDEX:
-      if (TEMPLATE_PARM_NUM_SIBLINGS (t1)
-	  != TEMPLATE_PARM_NUM_SIBLINGS (t2))
+      if (!(TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
+	    && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
+	    && (TEMPLATE_PARM_PARAMETER_PACK (t1)
+		== TEMPLATE_PARM_PARAMETER_PACK (t2))
+	    && comptypes (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
+			  TREE_TYPE (TEMPLATE_PARM_DECL (t2)), strict)))
 	return false;
-      return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
-	      && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
-	      && (TEMPLATE_PARM_PARAMETER_PACK (t1)
-		  == TEMPLATE_PARM_PARAMETER_PACK (t2))
-	      && same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
-			      TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
+      return comp_template_parms_siblings (t1, t2, strict);
 
     case TEMPLATE_ID_EXPR:
       {
 	unsigned ix;
 	tree vec1, vec2;
 
-	if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+	if (!compare_trees (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), strict))
 	  return false;
 	vec1 = TREE_OPERAND (t1, 1);
 	vec2 = TREE_OPERAND (t2, 1);
@@ -2352,8 +2357,9 @@ cp_tree_equal (tree t1, tree t2)
 	  return false;
 
 	for (ix = TREE_VEC_LENGTH (vec1); ix--;)
-	  if (!cp_tree_equal (TREE_VEC_ELT (vec1, ix),
-			      TREE_VEC_ELT (vec2, ix)))
+	  if (!compare_trees (TREE_VEC_ELT (vec1, ix),
+			      TREE_VEC_ELT (vec2, ix),
+			      strict))
 	    return false;
 
 	return true;
@@ -2368,16 +2374,17 @@ cp_tree_equal (tree t1, tree t2)
 	if (TREE_CODE (o1) != TREE_CODE (o2))
 	  return false;
 	if (TYPE_P (o1))
-	  return same_type_p (o1, o2);
+	  return comptypes (o1, o2, strict);
 	else
-	  return cp_tree_equal (o1, o2);
+	  return compare_trees (o1, o2, strict);
       }
 
     case MODOP_EXPR:
       {
 	tree t1_op1, t2_op1;
 
-	if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+	if (!compare_trees (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0),
+			    strict))
 	  return false;
 
 	t1_op1 = TREE_OPERAND (t1, 1);
@@ -2385,7 +2392,7 @@ cp_tree_equal (tree t1, tree t2)
 	if (TREE_CODE (t1_op1) != TREE_CODE (t2_op1))
 	  return false;
 
-	return cp_tree_equal (TREE_OPERAND (t1, 2), TREE_OPERAND (t2, 2));
+	return compare_trees (TREE_OPERAND (t1, 2), TREE_OPERAND (t2, 2), strict);
       }
 
     case PTRMEM_CST:
@@ -2394,18 +2401,18 @@ cp_tree_equal (tree t1, tree t2)
       if (PTRMEM_CST_MEMBER (t1) != PTRMEM_CST_MEMBER (t2))
 	return false;
 
-      return same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2));
+      return comptypes (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2), strict);
 
     case OVERLOAD:
       if (OVL_FUNCTION (t1) != OVL_FUNCTION (t2))
 	return false;
-      return cp_tree_equal (OVL_CHAIN (t1), OVL_CHAIN (t2));
+      return compare_trees (OVL_CHAIN (t1), OVL_CHAIN (t2), strict);
 
     case TRAIT_EXPR:
       if (TRAIT_EXPR_KIND (t1) != TRAIT_EXPR_KIND (t2))
 	return false;
-      return same_type_p (TRAIT_EXPR_TYPE1 (t1), TRAIT_EXPR_TYPE1 (t2))
-	&& same_type_p (TRAIT_EXPR_TYPE2 (t1), TRAIT_EXPR_TYPE2 (t2));
+      return comptypes (TRAIT_EXPR_TYPE1 (t1), TRAIT_EXPR_TYPE1 (t2), strict)
+	&& comptypes (TRAIT_EXPR_TYPE2 (t1), TRAIT_EXPR_TYPE2 (t2), strict);
 
     case CAST_EXPR:
     case STATIC_CAST_EXPR:
@@ -2414,16 +2421,18 @@ cp_tree_equal (tree t1, tree t2)
     case DYNAMIC_CAST_EXPR:
     case IMPLICIT_CONV_EXPR:
     case NEW_EXPR:
-      if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+      if (!comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
 	return false;
       /* Now compare operands as usual.  */
       break;
 
     case DEFERRED_NOEXCEPT:
-      return (cp_tree_equal (DEFERRED_NOEXCEPT_PATTERN (t1),
-			     DEFERRED_NOEXCEPT_PATTERN (t2))
-	      && comp_template_args (DEFERRED_NOEXCEPT_ARGS (t1),
-				     DEFERRED_NOEXCEPT_ARGS (t2)));
+      return (compare_trees (DEFERRED_NOEXCEPT_PATTERN (t1),
+			     DEFERRED_NOEXCEPT_PATTERN (t2),
+			     strict)
+	      && comp_template_args_real (DEFERRED_NOEXCEPT_ARGS (t1),
+					  DEFERRED_NOEXCEPT_ARGS (t2),
+					  NULL, NULL, strict));
       break;
 
     default:
@@ -2448,14 +2457,15 @@ cp_tree_equal (tree t1, tree t2)
 	  return false;
 
 	for (i = 0; i < n; ++i)
-	  if (!cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)))
+	  if (!compare_trees (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i),
+			      strict))
 	    return false;
 
 	return true;
       }
 
     case tcc_type:
-      return same_type_p (t1, t2);
+      return comptypes (t1, t2, strict);
     default:
       gcc_unreachable ();
     }
@@ -2463,6 +2473,15 @@ cp_tree_equal (tree t1, tree t2)
   return false;
 }
 
+/* Return truthvalue of whether T1 is the same tree structure as T2.
+   Return 1 if they are the same. Return 0 if they are different.  */
+
+bool
+cp_tree_equal (tree t1, tree t2)
+{
+  return compare_trees (t1, t2, COMPARE_STRICT);
+}
+
 /* The type of ARG when used as an lvalue.  */
 
 tree
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 91e7a0a..781683f 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -53,6 +53,7 @@ static tree rationalize_conditional_expr (enum tree_code, tree,
 static int comp_ptr_ttypes_real (tree, tree, int);
 static bool comp_except_types (tree, tree, bool);
 static bool comp_array_types (const_tree, const_tree, bool);
+static bool compparms_real (const_tree, const_tree, int);
 static tree pointer_diff (tree, tree, tree);
 static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t);
 static void casts_away_constness_r (tree *, tree *);
@@ -1119,13 +1120,56 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
   return true;
 }
 
+/* Return true iff the two instances of TEMPLATE_PARM_INDEX are
+   equivalent.  STRICT controls how the comparison is done, with the
+   same semantics as the last parameter of comptypes.  */
+
+bool
+comp_template_parms_siblings (tree index1,
+			      tree index2,
+			      int strict)
+{
+  tree siblings1, siblings2;
+
+  gcc_assert (index1 != NULL_TREE 
+	      && index2 != NULL_TREE
+	      && TREE_CODE (index1) == TREE_CODE (index2)
+	      && TREE_CODE (index1) == TEMPLATE_PARM_INDEX);
+
+  if (strict & COMPARE_NO_SIBLINGS)
+    return true;
+
+  siblings1 = TEMPLATE_PARM_SIBLINGS (index1);
+  siblings2 = TEMPLATE_PARM_SIBLINGS (index2);
+    
+  if (siblings1 == siblings2)
+    return true;
+
+  /* If T1 and T2 belong to different template parm lists let's assume
+     they are different.  */
+
+  if ((siblings1 != NULL_TREE) != (siblings2 != NULL_TREE))
+    return false;
+
+  if (TREE_VEC_LENGTH (siblings1) != TREE_VEC_LENGTH (siblings2))
+    return false;
+
+  if (!comp_template_parm_levels (siblings1, siblings2,
+				  strict | COMPARE_NO_SIBLINGS))
+    return false;
+
+  return true;
+}
+
 /* Compare the relative position of T1 and T2 into their respective
    template parameter list.
-   T1 and T2 must be template parameter types.
+   T1 and T2 must be template parameter types.  STRICT controls how
+   the comparison is done, with the same semantics as the for the last
+   parameter of comptypes.
    Return TRUE if T1 and T2 have the same position, FALSE otherwise.  */
 
 static bool
-comp_template_parms_position (tree t1, tree t2)
+comp_template_parms_position (tree t1, tree t2, int strict)
 {
   tree index1, index2;
   gcc_assert (t1 && t2
@@ -1137,19 +1181,26 @@ comp_template_parms_position (tree t1, tree t2)
   index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
   index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
 
-  /* If T1 and T2 belong to template parm lists of different size,
-     let's assume they are different.  */
-  if (TEMPLATE_PARM_NUM_SIBLINGS (index1)
-      != TEMPLATE_PARM_NUM_SIBLINGS (index2))
-    return false;
-
-  /* Then compare their relative position.  */
+  /* 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;
 
+  /* Don't compare levels of parms when we are in the process of
+     comparing siblings of a given template parm.  This is because the
+     TEMPLATE_PARM_SIBLINGS property of a template parm which level
+     has been reduced by tsubst still points to the original siblings,
+     which level is greater; while comparing those siblings with
+     another set of siblings, considering their levels can lead to
+     errors. */
+  if (!(strict & COMPARE_NO_SIBLINGS)
+      && (TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)))
+    return false;
+
+  if (!comp_template_parms_siblings (index1, index2, strict))
+    return false;
+
   return true;
 }
 
@@ -1233,11 +1284,12 @@ structural_comptypes (tree t1, tree t2, int strict)
 
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
-      if (!comp_template_parms_position (t1, t2))
+      if (!comp_template_parms_position (t1, t2, strict))
 	return false;
-      if (!comp_template_parms
+      if (!comp_template_parms_real
 	  (DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
-	   DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2))))
+	   DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2)),
+	   strict))
 	return false;
       if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
 	break;
@@ -1250,7 +1302,9 @@ structural_comptypes (tree t1, tree t2, int strict)
       if (TYPE_TEMPLATE_INFO (t1) && TYPE_TEMPLATE_INFO (t2)
 	  && (TYPE_TI_TEMPLATE (t1) == TYPE_TI_TEMPLATE (t2)
 	      || TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM)
-	  && comp_template_args (TYPE_TI_ARGS (t1), TYPE_TI_ARGS (t2)))
+	  && comp_template_args_real (TYPE_TI_ARGS (t1),
+				      TYPE_TI_ARGS (t2),
+				      NULL, NULL, strict))
 	break;
 
       if ((strict & COMPARE_BASE) && DERIVED_FROM_P (t1, t2))
@@ -1264,7 +1318,7 @@ structural_comptypes (tree t1, tree t2, int strict)
       if (!comptypes (TYPE_OFFSET_BASETYPE (t1), TYPE_OFFSET_BASETYPE (t2),
 		      strict & ~COMPARE_REDECLARATION))
 	return false;
-      if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+      if (!comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
 	return false;
       break;
 
@@ -1276,15 +1330,17 @@ structural_comptypes (tree t1, tree t2, int strict)
     case POINTER_TYPE:
       if (TYPE_MODE (t1) != TYPE_MODE (t2)
 	  || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)
-	  || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+	  || !comptypes (TREE_TYPE (t1), TREE_TYPE (t2),
+			 strict & ~COMPARE_REDECLARATION))
 	return false;
       break;
 
     case METHOD_TYPE:
     case FUNCTION_TYPE:
-      if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+      if (!comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
 	return false;
-      if (!compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2)))
+      if (!compparms_real (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2),
+			   strict))
 	return false;
       break;
 
@@ -1297,43 +1353,48 @@ structural_comptypes (tree t1, tree t2, int strict)
     case 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))
+      if (!comp_template_parms_position (t1, t2, strict))
 	return false;
       break;
 
     case TYPENAME_TYPE:
-      if (!cp_tree_equal (TYPENAME_TYPE_FULLNAME (t1),
-			  TYPENAME_TYPE_FULLNAME (t2)))
+      if (!compare_trees (TYPENAME_TYPE_FULLNAME (t1),
+			  TYPENAME_TYPE_FULLNAME (t2),
+			  strict))
 	return false;
       /* Qualifiers don't matter on scopes.  */
-      if (!same_type_ignoring_top_level_qualifiers_p (TYPE_CONTEXT (t1),
-						      TYPE_CONTEXT (t2)))
+      if (!same_type_ignoring_top_level_qualifiers_real_p (TYPE_CONTEXT (t1),
+							   TYPE_CONTEXT (t2),
+							   strict))
 	return false;
       break;
 
     case UNBOUND_CLASS_TEMPLATE:
-      if (!cp_tree_equal (TYPE_IDENTIFIER (t1), TYPE_IDENTIFIER (t2)))
+      if (!compare_trees (TYPE_IDENTIFIER (t1), TYPE_IDENTIFIER (t2),
+			  strict))
 	return false;
-      if (!same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2)))
+      if (!comptypes (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2), strict))
 	return false;
       break;
 
     case COMPLEX_TYPE:
-      if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+      if (!comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
 	return false;
       break;
 
     case VECTOR_TYPE:
       if (TYPE_VECTOR_SUBPARTS (t1) != TYPE_VECTOR_SUBPARTS (t2)
-	  || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+	  || !comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
 	return false;
       break;
 
     case TYPE_PACK_EXPANSION:
-      return (same_type_p (PACK_EXPANSION_PATTERN (t1),
-			   PACK_EXPANSION_PATTERN (t2))
-	      && comp_template_args (PACK_EXPANSION_EXTRA_ARGS (t1),
-				     PACK_EXPANSION_EXTRA_ARGS (t2)));
+	return (comptypes (PACK_EXPANSION_PATTERN (t1), 
+			   PACK_EXPANSION_PATTERN (t2),
+			   strict)
+		&& comp_template_args_real (PACK_EXPANSION_EXTRA_ARGS (t1),
+					    PACK_EXPANSION_EXTRA_ARGS (t2),
+					    NULL, NULL, strict));
 
     case DECLTYPE_TYPE:
       if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t1)
@@ -1342,14 +1403,16 @@ structural_comptypes (tree t1, tree t2, int strict)
 	      != DECLTYPE_FOR_LAMBDA_CAPTURE (t2))
 	  || (DECLTYPE_FOR_LAMBDA_PROXY (t1)
 	      != DECLTYPE_FOR_LAMBDA_PROXY (t2))
-          || !cp_tree_equal (DECLTYPE_TYPE_EXPR (t1), 
-                             DECLTYPE_TYPE_EXPR (t2)))
+          || !compare_trees (DECLTYPE_TYPE_EXPR (t1), 
+                             DECLTYPE_TYPE_EXPR (t2),
+			     strict))
         return false;
       break;
 
     case UNDERLYING_TYPE:
-      return same_type_p (UNDERLYING_TYPE_TYPE (t1), 
-			  UNDERLYING_TYPE_TYPE (t2));
+      return comptypes (UNDERLYING_TYPE_TYPE (t1), 
+			UNDERLYING_TYPE_TYPE (t2),
+			strict);
 
     default:
       return false;
@@ -1416,15 +1479,31 @@ comptypes (tree t1, tree t2, int strict)
 }
 
 /* Returns nonzero iff TYPE1 and TYPE2 are the same type, ignoring
-   top-level qualifiers.  */
+   top-level qualifiers.  STRICT controls how the type comparison is
+   done, with the same semantics as for the last parameter of
+   comptypes.  */
 
 bool
-same_type_ignoring_top_level_qualifiers_p (tree type1, tree type2)
+same_type_ignoring_top_level_qualifiers_real_p (tree type1,
+						tree type2,
+						int strict)
 {
   if (type1 == error_mark_node || type2 == error_mark_node)
     return false;
 
-  return same_type_p (TYPE_MAIN_VARIANT (type1), TYPE_MAIN_VARIANT (type2));
+  return comptypes (TYPE_MAIN_VARIANT (type1),
+		    TYPE_MAIN_VARIANT (type2),
+		    strict);
+}
+
+/* Returns nonzero iff TYPE1 and TYPE2 are the same type, ignoring
+   top-level qualifiers.  */
+
+bool
+same_type_ignoring_top_level_qualifiers_p (tree type1, tree type2)
+{
+  return same_type_ignoring_top_level_qualifiers_real_p (type1, type2,
+							 COMPARE_STRICT);
 }
 
 /* Returns 1 if TYPE1 is at least as qualified as TYPE2.  */
@@ -1479,10 +1558,10 @@ comp_cv_qual_signature (tree type1, tree type2)
 /* Return true if two parameter type lists PARMS1 and PARMS2 are
    equivalent in the sense that functions with those parameter types
    can have equivalent types.  The two lists must be equivalent,
-   element by element.  */
+   element by element.  STRICT controls how the comparison is done.  */
 
-bool
-compparms (const_tree parms1, const_tree parms2)
+static bool
+compparms_real (const_tree parms1, const_tree parms2, int strict)
 {
   const_tree t1, t2;
 
@@ -1497,12 +1576,23 @@ compparms (const_tree parms1, const_tree parms2)
 	 they fail to match.  */
       if (!t1 || !t2)
 	return false;
-      if (!same_type_p (TREE_VALUE (t1), TREE_VALUE (t2)))
+      if (!comptypes (TREE_VALUE (t1), TREE_VALUE (t2), strict))
 	return false;
     }
   return true;
 }
 
+/* Return true if two parameter type lists PARMS1 and PARMS2 are
+   equivalent in the sense that functions with those parameter types
+   can have equivalent types.  The two lists must be equivalent,
+   element by element.  */
+
+bool
+compparms (const_tree parms1, const_tree parms2)
+{
+  return compparms_real (parms1, parms2, COMPARE_STRICT);
+}
+
 
 /* Process a sizeof or alignof expression where the operand is a
    type.  */
diff --git a/gcc/testsuite/g++.dg/template/typedef39.C b/gcc/testsuite/g++.dg/template/typedef39.C
new file mode 100644
index 0000000..4ee23a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef39.C
@@ -0,0 +1,16 @@
+// Origin PR c++/50852
+// { dg-do compile }
+
+template<int d> class A;
+template<class T> struct B {typedef int K;typedef int L;};
+template<class U,class V> struct C
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W;
+};
+template<class U,int d> struct D
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W; // { dg-error "not a member" }
+};
+template class D<B<A<1> >,3>;
diff --git a/gcc/testsuite/g++.dg/template/typedef40.C b/gcc/testsuite/g++.dg/template/typedef40.C
new file mode 100644
index 0000000..6cd9766
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef40.C
@@ -0,0 +1,22 @@
+// Origin PR c++/50852
+// { dg-do compile }
+
+template<int d> class A;
+
+template<class T> struct B {typedef int K;typedef int L;};
+template<class U, void(*)(U&), class V> struct C
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W;
+};
+template<class U, void(*)(U&), int d> struct D
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W; // { dg-error "not a member" }
+};
+
+struct S;
+
+void f(B<A<1> >&);
+
+template class D<B<A<1> >, &f, 3>;
diff --git a/gcc/testsuite/g++.dg/template/typedef41.C b/gcc/testsuite/g++.dg/template/typedef41.C
new file mode 100644
index 0000000..17d2feb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef41.C
@@ -0,0 +1,19 @@
+// Origin PR c++/50852
+// { dg-do compile }
+
+template<int d> class A;
+
+template<class T> struct B {typedef int K;typedef int L;};
+template<class U, typename U::K, class V> struct C
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W;
+};
+template<class U, typename U::K, int d> struct D
+{
+    typedef typename U::L X;
+    typedef A<X::a-1> W; // { dg-error "not a member" }
+};
+
+
+template class D<B<A<1> >, 0, 3>;
-- 
1.7.6.5


-- 
		Dodji


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]