2013-08-03 Jason Merrill <jason@redhat.com>
+ DR 1286
+ * pt.c (get_underlying_template): New.
+ (convert_template_argument, lookup_template_class_1): Use it.
+
DR 1430
PR c++/51239
* pt.c (pack_expansion_args_count): Rename from
&& DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
}
+/* Return either TMPL or another template that it is equivalent to under DR
+ 1286: An alias that just changes the name of a template is equivalent to
+ the other template. */
+
+static tree
+get_underlying_template (tree tmpl)
+{
+ gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
+ while (DECL_ALIAS_TEMPLATE_P (tmpl))
+ {
+ tree result = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+ if (TYPE_TEMPLATE_INFO (result))
+ {
+ tree sub = TYPE_TI_TEMPLATE (result);
+ if (PRIMARY_TEMPLATE_P (sub)
+ && same_type_p (result, TREE_TYPE (sub)))
+ {
+ /* The alias type is equivalent to the pattern of the
+ underlying template, so strip the alias. */
+ tmpl = sub;
+ continue;
+ }
+ }
+ break;
+ }
+ return tmpl;
+}
+
/* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
must be a function or a pointer-to-function type, as specified
in [temp.arg.nontype]: disambiguate EXPR if it is an overload set,
tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
tree argparm;
+ /* Strip alias templates that are equivalent to another
+ template. */
+ arg = get_underlying_template (arg);
argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
if (coerce_template_template_parms (parmparm, argparm,
complain &= ~tf_user;
+ /* An alias that just changes the name of a template is equivalent to the
+ other template, so if any of the arguments are pack expansions, strip
+ the alias to avoid problems with a pack expansion passed to a non-pack
+ alias template parameter (DR 1430). */
+ if (pack_expansion_args_count (INNERMOST_TEMPLATE_ARGS (arglist)))
+ templ = get_underlying_template (templ);
+
if (DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
{
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
void
foo()
{
- // Below x and y don't have the same type, because Y and Z don't
- // designate the same template ...
+ // Below x and y have the same type (DR 1286)
X<Y> y;
X<Z> z;
- // ... So these must fail to compile.
- f(z); // { dg-error "" }
- g(y); // { dg-error "" }
+ // ... So these must compile.
+ f(z); // { dg-bogus "" }
+ g(y); // { dg-bogus "" }
}
template<class> struct A0 {};
--- /dev/null
+// PR c++/51239
+// { dg-require-effective-target c++11 }
+// This variant should work because tail is equivalent to list.
+
+template<class y, class... x>
+class list{};
+template<class a, class... b>
+using tail=list<a, b...>;
+template <class...T>
+void f(tail<T...>);
+
+int main()
+{
+ f<int,int>({});
+}
--- /dev/null
+// DR 1286: An alias template can be equivalent to an underlying template.
+// { dg-do compile { target c++11 } }
+
+template <class T, class U> struct same;
+template <class T> struct same<T,T> {};
+
+template <class T> struct A {};
+template <class T> using B = A<T>;
+
+template <template <class> class T> class C {};
+
+void f(C<B>) { } // { dg-final { scan-assembler "_Z1f1CI1AE" } }
+same<C<A>, C<B> > s;
--- /dev/null
+// DR 1286
+// { dg-do compile { target c++11 } }
+
+template <class,class> struct same;
+template <class T> struct same<T,T> {};
+
+template <class,class> struct different {};
+template <class T> struct different<T,T>;
+
+template<typename T, typename U = T> struct A;
+template<template <class...> class> struct X;
+
+// equivalent to A
+template<typename V, typename W>
+using B = A<V, W>;
+
+same<X<A>,X<B>> s1;
+
+// not equivalent to A: not all parameters used
+template<typename V, typename W>
+using C = A<V>;
+
+different<X<A>,X<C>> d1;
+
+// not equivalent to A: different number of parameters
+template<typename V>
+using D = A<V>;
+
+different<X<A>,X<D>> d2;
+
+// not equivalent to A: template-arguments in wrong order
+template<typename V, typename W>
+using E = A<W, V>;
+
+different<X<A>,X<E>> d3;
+
+// equivalent to A: default arguments not considered
+template<typename V, typename W = int>
+using F = A<V, W>;
+
+same<X<A>,X<F>> s2;
+
+// equivalent to A and B
+template<typename V, typename W>
+using G = A<V, W>;
+
+same<X<A>,X<G>> s3;
+same<X<B>,X<G>> s3b;
+
+// equivalent to E
+template<typename V, typename W>
+using H = E<V, W>;
+
+same<X<E>,X<H>> s4;
+
+// not equivalent to A: argument not identifier
+template<typename V, typename W>
+using I = A<V, typename W::type>;
+
+different<X<A>,X<I>> d4;