diff options
author | Jason Merrill <jason@redhat.com> | 2013-08-03 16:32:08 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2013-08-03 16:32:08 -0400 |
commit | 45d765871b6744d2fe519a61a1d15ff4d613388f (patch) | |
tree | 9218647d81212608b0e192ef6ad5cce3a8330fe0 /gcc | |
parent | 9e356571d442ca5241117b05428fb5055b55d0aa (diff) | |
download | gcc-45d765871b6744d2fe519a61a1d15ff4d613388f.zip gcc-45d765871b6744d2fe519a61a1d15ff4d613388f.tar.gz gcc-45d765871b6744d2fe519a61a1d15ff4d613388f.tar.bz2 |
DR 1286
DR 1286
* pt.c (get_underlying_template): New.
(convert_template_argument, lookup_template_class_1): Use it.
From-SVN: r201470
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/pt.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/alias-decl-33a.C | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286.C | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286a.C | 60 |
6 files changed, 134 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8b9b997..5587ac1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bbaeb7d..d03c1cf 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5111,6 +5111,34 @@ alias_template_specialization_p (const_tree t) && 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, @@ -6319,6 +6347,9 @@ convert_template_argument (tree parm, 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, @@ -7177,6 +7208,13 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, 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 diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C index c5760cf..f38f993 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C @@ -10,14 +10,13 @@ void g(X<Z>); 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 {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-33a.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-33a.C new file mode 100644 index 0000000..a1c442e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-33a.C @@ -0,0 +1,15 @@ +// 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>({}); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286.C new file mode 100644 index 0000000..0c545c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286.C @@ -0,0 +1,13 @@ +// 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; diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286a.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286a.C new file mode 100644 index 0000000..1780c9a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286a.C @@ -0,0 +1,60 @@ +// 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; |