[PATCH] Fix PR c++/30044
gcc/cp/ChangeLog: * parser.c (cp_parser_template_parameter_list): Update current_template_parms right after processing a paramater. * pt.c (template_parms_to_args): Remove obsolete hack for giving template template arguments the proper level. (check_default_tmpl_args): Account for tested template parameter_lists. (splite_late_return_type): Remove obsolete hack for giving template template arguments the proper level. gcc/testsuite/ChangeLog * g++.dg/cpp0x/auto45.C: New test. * g++.dg/template/pr30044.C: New test. * g++.dg/template/crash83.C: Accept any error string. * g++.dg/cpp0x/variadic18.C: Adjust to not shadow template parameters. * g++.dg/cpp0x/variadic18.C: Likewise * g++.dg/template/canon-type-13.C: Likewise. * g++.old-deja/g++.pt/ttp42.C: Likewise. From-SVN: r224859
This commit is contained in:
parent
8289f048f0
commit
1a8f8908d2
@ -1,3 +1,14 @@
|
||||
2015-06-23 Patrick Palka <ppalka@gcc.gnu.org>
|
||||
|
||||
* parser.c (cp_parser_template_parameter_list): Update
|
||||
current_template_parms right after processing a paramater.
|
||||
* pt.c (template_parms_to_args): Remove obsolete hack for
|
||||
giving template template arguments the proper level.
|
||||
(check_default_tmpl_args): Account for tested template
|
||||
parameter_lists.
|
||||
(splite_late_return_type): Remove obsolete hack for giving
|
||||
template template arguments the proper level.
|
||||
|
||||
2015-06-23 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/65879
|
||||
|
@ -13273,6 +13273,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
|
||||
|
||||
begin_template_parm_list ();
|
||||
|
||||
current_template_parms
|
||||
= tree_cons (size_int (processing_template_decl),
|
||||
make_tree_vec (0),
|
||||
current_template_parms);
|
||||
|
||||
/* The loop below parses the template parms. We first need to know
|
||||
the total number of template parms to be able to compute proper
|
||||
canonical types of each dependent type. So after the loop, when
|
||||
@ -13285,6 +13290,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
|
||||
bool is_non_type;
|
||||
bool is_parameter_pack;
|
||||
location_t parm_loc;
|
||||
tree parameter_vec;
|
||||
|
||||
/* Parse the template-parameter. */
|
||||
parm_loc = cp_lexer_peek_token (parser->lexer)->location;
|
||||
@ -13309,8 +13315,27 @@ cp_parser_template_parameter_list (cp_parser* parser)
|
||||
break;
|
||||
/* Otherwise, consume the `,' token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
/* Add the parameter we just processed to current_template_parms. */
|
||||
|
||||
parameter_vec = make_tree_vec
|
||||
(TREE_VEC_LENGTH (TREE_VALUE (current_template_parms)) + 1);
|
||||
|
||||
for (int i = 0; i < TREE_VEC_LENGTH (parameter_vec) - 1; i++)
|
||||
TREE_VEC_ELT (parameter_vec, i)
|
||||
= TREE_VEC_ELT (TREE_VALUE (current_template_parms), i);
|
||||
|
||||
TREE_VEC_ELT (parameter_vec, TREE_VEC_LENGTH (parameter_vec) - 1)
|
||||
= tree_last (parameter_list);
|
||||
|
||||
current_template_parms
|
||||
= tree_cons (TREE_PURPOSE (current_template_parms),
|
||||
parameter_vec,
|
||||
TREE_CHAIN (current_template_parms));
|
||||
}
|
||||
|
||||
current_template_parms = TREE_CHAIN (current_template_parms);
|
||||
|
||||
return end_template_parm_list (parameter_list);
|
||||
}
|
||||
|
||||
|
33
gcc/cp/pt.c
33
gcc/cp/pt.c
@ -3989,21 +3989,6 @@ template_parms_to_args (tree parms)
|
||||
args = a;
|
||||
}
|
||||
|
||||
if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
|
||||
/* This can happen for template parms of a template template
|
||||
parameter, e.g:
|
||||
|
||||
template<template<class T, class U> class TT> struct S;
|
||||
|
||||
Consider the level of the parms of TT; T and U both have
|
||||
level 2; TT has no template parm of level 1. So in this case
|
||||
the first element of full_template_args is NULL_TREE. If we
|
||||
leave it like this TMPL_ARGS_DEPTH on args returns 1 instead
|
||||
of 2. This will make tsubst wrongly consider that T and U
|
||||
have level 1. Instead, let's create a dummy vector as the
|
||||
first element of full_template_args so that TMPL_ARGS_DEPTH
|
||||
returns the correct depth for args. */
|
||||
TREE_VEC_ELT (args, 0) = make_tree_vec (1);
|
||||
return args;
|
||||
}
|
||||
|
||||
@ -4646,6 +4631,9 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary,
|
||||
else
|
||||
msg = G_("default argument for template parameter for class enclosing %qD");
|
||||
|
||||
/* By default check everything. */
|
||||
last_level_to_check = 1;
|
||||
|
||||
if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
|
||||
/* If we're inside a class definition, there's no need to
|
||||
examine the parameters to the class itself. On the one
|
||||
@ -4655,10 +4643,12 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary,
|
||||
struct S { template <class U> void f(U); };
|
||||
Here the default argument for `S' has no bearing on the
|
||||
declaration of `f'. */
|
||||
last_level_to_check = template_class_depth (current_class_type) + 1;
|
||||
else
|
||||
/* Check everything. */
|
||||
last_level_to_check = 0;
|
||||
last_level_to_check += template_class_depth (current_class_type);
|
||||
|
||||
if (processing_template_parmlist)
|
||||
/* Likewise for parameters outside of the nested parameter list we have
|
||||
just finished defining. */
|
||||
last_level_to_check += processing_template_parmlist;
|
||||
|
||||
for (parm_level = parms;
|
||||
parm_level && TMPL_PARMS_DEPTH (parm_level) >= last_level_to_check;
|
||||
@ -22392,11 +22382,6 @@ splice_late_return_type (tree type, tree late_return_type)
|
||||
return type;
|
||||
argvec = make_tree_vec (1);
|
||||
TREE_VEC_ELT (argvec, 0) = late_return_type;
|
||||
if (processing_template_parmlist)
|
||||
/* For a late-specified return type in a template type-parameter, we
|
||||
need to add a dummy argument level for its parmlist. */
|
||||
argvec = add_to_template_args
|
||||
(make_tree_vec (processing_template_parmlist), argvec);
|
||||
if (current_template_parms)
|
||||
argvec = add_to_template_args (current_template_args (), argvec);
|
||||
return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
|
||||
|
@ -1,3 +1,14 @@
|
||||
2015-06-23 Patrick Palka <ppalka@gcc.gnu.org>
|
||||
|
||||
* g++.dg/cpp0x/auto45.C: New test.
|
||||
* g++.dg/template/pr30044.C: New test.
|
||||
* g++.dg/template/crash83.C: Accept any error string.
|
||||
* g++.dg/cpp0x/variadic18.C: Adjust to not shadow template
|
||||
parameters.
|
||||
* g++.dg/cpp0x/variadic18.C: Likewise
|
||||
* g++.dg/template/canon-type-13.C: Likewise.
|
||||
* g++.old-deja/g++.pt/ttp42.C: Likewise.
|
||||
|
||||
2015-06-23 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
* c-c++-common/Wlogical-op-3.c: New test.
|
||||
|
5
gcc/testsuite/g++.dg/cpp0x/auto45.C
Normal file
5
gcc/testsuite/g++.dg/cpp0x/auto45.C
Normal file
@ -0,0 +1,5 @@
|
||||
// Addendum to auto23.C, now with nested template parameter lists
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template<template <auto f()->int> class> struct A { };
|
||||
template<template <template <auto f()->int> class> class> struct B { };
|
@ -1,7 +1,7 @@
|
||||
// { dg-do compile { target c++11 } }
|
||||
template<typename...> class tuple { };
|
||||
|
||||
template<typename T, template<typename T> class... Metafunctions>
|
||||
template<typename T, template<typename U> class... Metafunctions>
|
||||
struct apply_all
|
||||
{
|
||||
typedef tuple<typename Metafunctions<T>::type...> type;
|
||||
|
@ -4,7 +4,7 @@ struct tuple {
|
||||
static const int value = 0;
|
||||
};
|
||||
|
||||
template<typename T, template<class T> class... Metafunctions>
|
||||
template<typename T, template<class U> class... Metafunctions>
|
||||
struct tuple<Metafunctions<T>...> {
|
||||
static const int value = 1;
|
||||
};
|
||||
|
@ -11,7 +11,7 @@ struct S1
|
||||
{
|
||||
};
|
||||
|
||||
template<class T, template<class T> class A, template<class T> class B = A>
|
||||
template<class T, template<class U> class A, template<class U> class B = A>
|
||||
struct C
|
||||
{
|
||||
B<T> m;
|
||||
|
@ -2,4 +2,4 @@
|
||||
|
||||
template<int> struct A {};
|
||||
|
||||
template<typename = class A<0>: > struct B {}; // { dg-error "explicit specialization|expected" }
|
||||
template<typename = class A<0>: > struct B {}; // { dg-error "" }
|
||||
|
16
gcc/testsuite/g++.dg/template/pr30044.C
Normal file
16
gcc/testsuite/g++.dg/template/pr30044.C
Normal file
@ -0,0 +1,16 @@
|
||||
// PR c++/30044
|
||||
|
||||
template <typename T1, typename T2, template <T2> class Comp, class Result = Comp<1> >
|
||||
struct sort { };
|
||||
|
||||
|
||||
template <typename Type, template <Type, Type> class Comp, class Result = Comp<1, 2> >
|
||||
struct sort2 { };
|
||||
|
||||
template <typename Type, template <int, Type> class Comp, class Result = Comp<1, 2> >
|
||||
struct sort3 { };
|
||||
|
||||
template <template <typename T1, typename T2, template <T2> class Comp, class Result = Comp<1> > class Foo>
|
||||
struct sort4 { };
|
||||
|
||||
|
@ -89,7 +89,7 @@ namespace __gnu_test {
|
||||
SharedInfo->first=ptr;
|
||||
}
|
||||
};
|
||||
template <class T, template<class T> class ItType> struct test_container {
|
||||
template <class T, template<class U> class ItType> struct test_container {
|
||||
typename ItType<T>::ContainerType bounds;
|
||||
test_container(T* _first, T* _last):bounds(_first, _last) {
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// { dg-do run }
|
||||
template <class T, template <class T> class C>
|
||||
template <class T, template <class U> class C>
|
||||
struct X
|
||||
{};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user