Fix PR c++/30044
gcc/cp/ChangeLog:
PR c++/30044
* pt.c (begin_template_parm_list): Add a dummy parameter level
to current_template_parms.
(end_template_parm_list): Remove the dummy parameter level
before adding the real one.
(tsubst): Don't attempt to substitute for template parameters
corresponding to a dummy argument level.
(template_parms_to_args): Remove obsolete hack for
giving template template arguments the proper level.
(splite_late_return_type): Remove obsolete hack for giving
template template arguments the proper level.
* error.c (dump_template_decl): Don't print dummy template
levels.
gcc/testsuite/ChangeLog
PR c++/30044
* g++.dg/cpp0x/auto46.C: New test.
* g++.dg/template/pr30044.C: New test.
* g++.dg/template/shadow2.C: New test.
* g++.dg/template/error55.C: New test.
* g++.dg/template/crash83.C: Accept any error string.
* g++.dg/cpp0x/variadic18.C: Adjust to avoid shadowing template
parameters.
* g++.dg/cpp0x/variadic18.C: Likewise
* g++.dg/template/canon-type-13.C: Likewise.
* g++.old-deja/g++.pt/ttp42.C: Likewise.
* g++.dg/torture/
20070621-1.C: Likewise.
From-SVN: r225706
+2015-07-10 Patrick Palka <ppalka@gcc.gnu.org>
+
+ PR c++/30044
+ * pt.c (begin_template_parm_list): Add a dummy parameter level
+ to current_template_parms.
+ (end_template_parm_list): Remove the dummy parameter level
+ before adding the real one.
+ (tsubst): Don't attempt to substitute for template parameters
+ corresponding to a dummy argument level.
+ (template_parms_to_args): Remove obsolete hack for
+ giving template template arguments the proper level.
+ (splite_late_return_type): Remove obsolete hack for giving
+ template template arguments the proper level.
+ * error.c (dump_template_decl): Don't print dummy template
+ levels.
+
2015-07-10 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/54521
tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms);
int len = TREE_VEC_LENGTH (inner_parms);
+ if (len == 0)
+ {
+ /* Skip over the dummy template levels of a template template
+ parm. */
+ gcc_assert (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TEMPLATE_PARM);
+ continue;
+ }
+
pp_cxx_ws_string (pp, "template");
pp_cxx_begin_template_argument_list (pp);
++processing_template_decl;
++processing_template_parmlist;
note_template_header (0);
+
+ /* Add a dummy parameter level while we process the parameter list. */
+ current_template_parms
+ = tree_cons (size_int (processing_template_decl),
+ make_tree_vec (0),
+ current_template_parms);
}
/* This routine is called when a specialization is declared. If it is
tree parm, next;
tree saved_parmlist = make_tree_vec (list_length (parms));
+ /* Pop the dummy parameter level and add the real one. */
+ current_template_parms = TREE_CHAIN (current_template_parms);
+
current_template_parms
= tree_cons (size_int (processing_template_decl),
saved_parmlist, current_template_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;
}
template_parm_level_and_index (t, &level, &idx);
levels = TMPL_ARGS_DEPTH (args);
- if (level <= levels)
+ if (level <= levels
+ && TREE_VEC_LENGTH (TMPL_ARGS_LEVEL (args, level)) > 0)
{
arg = TMPL_ARG (args, level, idx);
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);
+2015-07-10 Patrick Palka <ppalka@gcc.gnu.org>
+
+ PR c++/30044
+ * g++.dg/cpp0x/auto46.C: New test.
+ * g++.dg/template/pr30044.C: New test.
+ * g++.dg/template/shadow2.C: New test.
+ * g++.dg/template/error55.C: New test.
+ * g++.dg/template/crash83.C: Accept any error string.
+ * g++.dg/cpp0x/variadic18.C: Adjust to avoid shadowing template
+ parameters.
+ * g++.dg/cpp0x/variadic18.C: Likewise
+ * g++.dg/template/canon-type-13.C: Likewise.
+ * g++.old-deja/g++.pt/ttp42.C: Likewise.
+ * g++.dg/torture/20070621-1.C: Likewise.
+
2015-07-10 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/54521
--- /dev/null
+// 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 { };
// { 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;
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;
};
{
};
-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;
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 "" }
--- /dev/null
+// Check that template template parameters get printed properly in error
+// messages.
+
+template <template <class A> class B>
+struct Y
+{
+ B<5> y; // { dg-error "for 'template<class A> class B'" }
+};
--- /dev/null
+// 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 { };
--- /dev/null
+template <class A, // { dg-error "shadows template parm 'class A'" }
+ template <class A> class B> // { dg-error "declaration of 'class A'" }
+class X;
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) {
}
// { dg-do run }
-template <class T, template <class T> class C>
+template <class T, template <class U> class C>
struct X
{};