From bb84c6699c15624535b1e3c6cf1ef914e58e9335 Mon Sep 17 00:00:00 2001 From: jason Date: Sat, 3 Aug 2013 20:32:08 +0000 Subject: [PATCH] DR 1286 * pt.c (get_underlying_template): New. (convert_template_argument, lookup_template_class_1): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@201470 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 4 ++ gcc/cp/pt.c | 38 ++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C | 9 ++-- gcc/testsuite/g++.dg/cpp0x/alias-decl-33a.C | 15 +++++++ gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286.C | 13 ++++++ gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286a.C | 60 +++++++++++++++++++++++++ 6 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-33a.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1286a.C 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 + 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); 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; X 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 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 list{}; +template +using tail=list; +template +void f(tail); + +int main() +{ + f({}); +} 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 struct same; +template struct same {}; + +template struct A {}; +template using B = A; + +template