Normally tsubst substitutes into the TREE_TYPE of the argument before
proceeding; that's wrong for an auto template parameter, which should
just get the appropriate type from its non-type argument.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 63a21767d094ac5c7b1a1ca0cd3d0366411c1a77
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Mar 20 15:36:49 2017 -0400

            PR c++/80096 - ICE with C++17 non-type auto.
    
            * pt.c (tsubst): Delay tsubst of type of template non-type
            parameter.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f180710..a4bf890 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13388,6 +13388,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
   if (type
       && code != TYPENAME_TYPE
       && code != TEMPLATE_TYPE_PARM
+      && code != TEMPLATE_PARM_INDEX
       && code != IDENTIFIER_NODE
       && code != FUNCTION_TYPE
       && code != METHOD_TYPE)
@@ -13690,6 +13691,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
            break;
 
          case TEMPLATE_PARM_INDEX:
+           /* OK, now substitute the type of the non-type parameter.  We
+              couldn't do it earlier because it might be an auto parameter,
+              and we wouldn't need to if we had an argument.  */
+           type = tsubst (type, args, complain, in_decl);
            r = reduce_template_parm_level (t, type, levels, args, complain);
            break;
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype-auto10.C 
b/gcc/testsuite/g++.dg/cpp1z/nontype-auto10.C
new file mode 100644
index 0000000..381ed51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/nontype-auto10.C
@@ -0,0 +1,9 @@
+// PR c++/80096
+// { dg-options -std=c++1z }
+
+template<auto> struct A
+{
+  template<int> struct B {};
+};
+
+A<0> a;

Reply via email to