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;