re PR c++/30044 (ICE in tsubst, at cp/pt.c:7359)
authorPatrick Palka <ppalka@gcc.gnu.org>
Fri, 10 Jul 2015 23:21:39 +0000 (23:21 +0000)
committerPatrick Palka <ppalka@gcc.gnu.org>
Fri, 10 Jul 2015 23:21:39 +0000 (23:21 +0000)
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

14 files changed:
gcc/cp/ChangeLog
gcc/cp/error.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/auto46.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic18.C
gcc/testsuite/g++.dg/cpp0x/variadic19.C
gcc/testsuite/g++.dg/template/canon-type-13.C
gcc/testsuite/g++.dg/template/crash83.C
gcc/testsuite/g++.dg/template/error55.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/pr30044.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/shadow2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/torture/20070621-1.C
gcc/testsuite/g++.old-deja/g++.pt/ttp42.C

index 9d9e0c1..2b46fbd 100644 (file)
@@ -1,3 +1,19 @@
+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
index b2b0638..b811df2 100644 (file)
@@ -1295,6 +1295,14 @@ dump_template_decl (cxx_pretty_printer *pp, tree t, int flags)
          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);
 
index 8c72a61..064cbfd 100644 (file)
@@ -657,6 +657,12 @@ begin_template_parm_list (void)
   ++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
@@ -3888,6 +3894,9 @@ end_template_parm_list (tree parms)
   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);
@@ -4023,21 +4032,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;
 }
 
@@ -12073,7 +12067,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
        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);
 
@@ -22440,11 +22435,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);
index dde2803..fae1def 100644 (file)
@@ -1,3 +1,18 @@
+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
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto46.C b/gcc/testsuite/g++.dg/cpp0x/auto46.C
new file mode 100644 (file)
index 0000000..09e9f44
--- /dev/null
@@ -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 { };
index fc0e2dd..57fdc86 100644 (file)
@@ -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;
index 0ae2672..3be9bb0 100644 (file)
@@ -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;
 };
index 4f3702b..5a8d37d 100644 (file)
@@ -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;
index b83dd21..7dcbed9 100644 (file)
@@ -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 "" }
diff --git a/gcc/testsuite/g++.dg/template/error55.C b/gcc/testsuite/g++.dg/template/error55.C
new file mode 100644 (file)
index 0000000..41f9595
--- /dev/null
@@ -0,0 +1,8 @@
+// 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'" }
+};
diff --git a/gcc/testsuite/g++.dg/template/pr30044.C b/gcc/testsuite/g++.dg/template/pr30044.C
new file mode 100644 (file)
index 0000000..415e6f0
--- /dev/null
@@ -0,0 +1,14 @@
+// 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 { };
diff --git a/gcc/testsuite/g++.dg/template/shadow2.C b/gcc/testsuite/g++.dg/template/shadow2.C
new file mode 100644 (file)
index 0000000..7f6a6dc
--- /dev/null
@@ -0,0 +1,3 @@
+template <class A, // { dg-error "shadows template parm 'class A'" }
+          template <class A> class B> // { dg-error "declaration of 'class A'" }
+class X;
index 15d1ac7..9bd8cc3 100644 (file)
@@ -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)     {
   }
index 53bdae1..a2ac239 100644 (file)
@@ -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
 {};