DR 1558
authorJason Merrill <jason@redhat.com>
Sat, 8 Nov 2014 06:06:42 +0000 (01:06 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 8 Nov 2014 06:06:42 +0000 (01:06 -0500)
DR 1558
* pt.c (dependent_alias_template_spec_p): New.
(dependent_type_p_r): Handle dependent alias template specialization.
(template_args_equal): A dependent alias template specializations
is not equal to its underlying type as a template argument.
* tree.c (strip_typedefs): Don't strip a dependent alias
template-id.

From-SVN: r217250

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1558.C [new file with mode: 0644]

index 132b9e1..a831d62 100644 (file)
@@ -1,5 +1,13 @@
 2014-11-07  Jason Merrill  <jason@redhat.com>
 
+       DR 1558
+       * pt.c (dependent_alias_template_spec_p): New.
+       (dependent_type_p_r): Handle dependent alias template specialization.
+       (template_args_equal): A dependent alias template specializations
+       is not equal to its underlying type as a template argument.
+       * tree.c (strip_typedefs): Don't strip a dependent alias
+       template-id.
+
        * parser.c (cp_parser_unqualified_id): Handle __func__ here.
        (cp_parser_primary_expression): Not here.
 
index abc3d6f..74636df 100644 (file)
@@ -5692,6 +5692,7 @@ extern tree fold_non_dependent_expr               (tree);
 extern tree fold_non_dependent_expr_sfinae     (tree, tsubst_flags_t);
 extern bool alias_type_or_template_p            (tree);
 extern bool alias_template_specialization_p     (const_tree);
+extern bool dependent_alias_template_spec_p     (const_tree);
 extern bool explicit_class_specialization_p     (tree);
 extern bool push_tinst_level                    (tree);
 extern bool push_tinst_level_loc                (tree, location_t);
index 2cf10f4..fa9652f 100644 (file)
@@ -5268,7 +5268,7 @@ alias_type_or_template_p (tree t)
          || DECL_ALIAS_TEMPLATE_P (t));
 }
 
-/* Return TRUE iff is a specialization of an alias template.  */
+/* Return TRUE iff is a specialization of an alias template.  */
 
 bool
 alias_template_specialization_p (const_tree t)
@@ -5282,6 +5282,16 @@ alias_template_specialization_p (const_tree t)
          && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
 }
 
+/* Return TRUE iff T is a specialization of an alias template with
+   dependent template-arguments.  */
+
+bool
+dependent_alias_template_spec_p (const_tree t)
+{
+  return (alias_template_specialization_p (t)
+         && any_dependent_template_arguments_p (TYPE_TI_ARGS (t)));
+}
+
 /* Return the number of innermost template parameters in TMPL.  */
 
 static int
@@ -7217,7 +7227,24 @@ template_args_equal (tree ot, tree nt)
       return template_args_equal (ot, nt);
     }
   else if (TYPE_P (nt))
-    return TYPE_P (ot) && same_type_p (ot, nt);
+    {
+      if (!TYPE_P (ot))
+       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)
+       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);
+    }
   else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
     return 0;
   else
@@ -20719,8 +20746,10 @@ dependent_type_p_r (tree type)
   if (TREE_CODE (type) == TYPENAME_TYPE)
     return true;
   /* -- a cv-qualified type where the cv-unqualified type is
-       dependent.  */
-  type = TYPE_MAIN_VARIANT (type);
+       dependent.
+     No code is necessary for this bullet; the code below handles
+     cv-qualified types, and we don't want to strip aliases with
+     TYPE_MAIN_VARIANT because of DR 1558.  */
   /* -- a compound type constructed from any dependent type.  */
   if (TYPE_PTRMEM_P (type))
     return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
@@ -20763,9 +20792,9 @@ dependent_type_p_r (tree type)
     return true;
   /* ... or any of the template arguments is a dependent type or
        an expression that is type-dependent or value-dependent.  */
-  else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
+  else if (TYPE_TEMPLATE_INFO (type)
           && (any_dependent_template_arguments_p
-              (INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)))))
+              (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (type)))))
     return true;
 
   /* All TYPEOF_TYPEs, DECLTYPE_TYPEs, and UNDERLYING_TYPEs are
index 32e7bd5..e0c2af1 100644 (file)
@@ -1244,6 +1244,11 @@ strip_typedefs (tree t)
   if (t == TYPE_CANONICAL (t))
     return t;
 
+  if (dependent_alias_template_spec_p (t))
+    /* DR 1558: However, if the template-id is dependent, subsequent
+       template argument substitution still applies to the template-id.  */
+    return t;
+
   switch (TREE_CODE (t))
     {
     case POINTER_TYPE:
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1558.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1558.C
new file mode 100644 (file)
index 0000000..2bbb138
--- /dev/null
@@ -0,0 +1,14 @@
+// DR 1558 still applies when using void_t as a template-argument.
+// { dg-do compile { target c++11 } }
+
+template<typename...> using void_t = void;
+template<class T> struct A { };
+struct B { typedef int foo; };
+template<typename T> A<void_t<typename T::foo>> f(); // { dg-error "int" }
+template<typename T> A<void> g();
+int main()
+{
+  f<B>();
+  g<int>();
+  f<int>(); // { dg-error "no match" }
+}