re PR c++/64359 (alias_template_specialization_p & template_args_equal show up high...
authorJason Merrill <jason@redhat.com>
Sun, 21 Dec 2014 05:00:43 +0000 (00:00 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 21 Dec 2014 05:00:43 +0000 (00:00 -0500)
PR c++/64359
* pt.c (iterative_hash_template_arg): Hash alias specializations
differently from their TYPE_CANONICAL.
(alias_template_specialization_p): Optimize.
(template_args_equal): Optimize alias handling.
(dependent_alias_template_spec_p): Only check innermost args.

From-SVN: r218995

gcc/cp/ChangeLog
gcc/cp/pt.c

index 7fcad878af77fed2226dc4db8976955c5d9b08b3..8802e59b87d1929abb180995255c89b7ce1dc655 100644 (file)
@@ -1,3 +1,12 @@
+2014-12-20  Jason Merrill  <jason@redhat.com>
+
+       PR c++/64359
+       * pt.c (iterative_hash_template_arg): Hash alias specializations
+       differently from their TYPE_CANONICAL.
+       (alias_template_specialization_p): Optimize.
+       (template_args_equal): Optimize alias handling.
+       (dependent_alias_template_spec_p): Only check innermost args.
+
 2014-12-19  Kai Tietz  <ktietz@redhat.com>
 
        PR c++/61198
index 15d304af635e26462012adfa15644d32945047fe..f5bd842df0eb4f78dfdcc105cd42ae463c605de7 100644 (file)
@@ -1674,6 +1674,18 @@ iterative_hash_template_arg (tree arg, hashval_t val)
   switch (tclass)
     {
     case tcc_type:
+      if (alias_template_specialization_p (arg))
+       {
+         // We want an alias specialization that survived strip_typedefs
+         // to hash differently from its TYPE_CANONICAL, to avoid hash
+         // collisions that compare as different in template_args_equal.
+         // These could be dependent specializations that strip_typedefs
+         // left alone, or untouched specializations because
+         // coerce_template_parms returns the unconverted template
+         // arguments if it sees incomplete argument packs.
+         tree ti = TYPE_TEMPLATE_INFO (arg);
+         return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti));
+       }
       if (TYPE_CANONICAL (arg))
        return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
                                      val);
@@ -5314,13 +5326,19 @@ alias_type_or_template_p (tree t)
 bool
 alias_template_specialization_p (const_tree t)
 {
-  if (t == NULL_TREE)
-    return false;
-  
-  return (TYPE_P (t)
-         && TYPE_TEMPLATE_INFO (t)
-         && PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (t))
-         && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
+  /* It's an alias template specialization if it's an alias and its
+     TYPE_NAME is a specialization of a primary template.  */
+  if (TYPE_ALIAS_P (t))
+    {
+      tree name = TYPE_NAME (t);
+      if (DECL_LANG_SPECIFIC (name))
+       if (tree ti = DECL_TEMPLATE_INFO (name))
+         {
+           tree tmpl = TI_TEMPLATE (ti);
+           return PRIMARY_TEMPLATE_P (tmpl);
+         }
+    }
+  return false;
 }
 
 /* Return TRUE iff T is a specialization of an alias template with
@@ -5330,7 +5348,8 @@ bool
 dependent_alias_template_spec_p (const_tree t)
 {
   return (alias_template_specialization_p (t)
-         && any_dependent_template_arguments_p (TYPE_TI_ARGS (t)));
+         && (any_dependent_template_arguments_p
+             (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (t)))));
 }
 
 /* Return the number of innermost template parameters in TMPL.  */
@@ -7283,16 +7302,12 @@ template_args_equal (tree ot, tree nt)
        return false;
       /* Don't treat an alias template specialization with dependent
         arguments as equivalent to its underlying type when used as a
-        template argument; we need them to hash differently.  */
-      bool ndep = dependent_alias_template_spec_p (nt);
-      ++processing_template_decl;
-      bool odep = dependent_alias_template_spec_p (ot);
-      --processing_template_decl;
-      if (ndep != odep)
+        template argument; we need them to be distinct so that we
+        substitute into the specialization arguments at instantiation
+        time.  And aliases can't be equivalent without being ==, so
+        we don't need to look any deeper.  */
+      if (TYPE_ALIAS_P (nt) || TYPE_ALIAS_P (ot))
        return false;
-      else if (ndep)
-       return (TYPE_TI_TEMPLATE (nt) == TYPE_TI_TEMPLATE (ot)
-               && template_args_equal (TYPE_TI_ARGS (nt), TYPE_TI_ARGS (ot)));
       else
        return same_type_p (ot, nt);
     }