Here, when we try to look up a constant variable from an enclosing function when instantiating a generic lambda outside of the context of that function, we make a dummy instantiation to use. In this case, the initializer refers to the variable, so we infinitely recurse until we run out of stack. Fixed by remembering the dummy instantiation before we try to instantiate the initializer.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit a6a6873ba58c4e19e938214a35370f8a4cb02235 Author: Jason Merrill <ja...@redhat.com> Date: Mon Mar 20 13:28:55 2017 -0400 PR c++/79640 - infinite recursion with generic lambda. * pt.c (tsubst_copy) [VAR_DECL]: Register the dummy instantiation before substituting its initializer. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b8ce9fe..f180710 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -14581,6 +14581,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) local static or constant. Building a new VAR_DECL should be OK in all those cases. */ r = tsubst_decl (t, args, complain); + if (local_specializations) + /* Avoid infinite recursion (79640). */ + register_local_specialization (r, t); if (decl_maybe_constant_var_p (r)) { /* We can't call cp_finish_decl, so handle the diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const3.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const3.C new file mode 100644 index 0000000..9c9dbac --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const3.C @@ -0,0 +1,15 @@ +// PR c++/79640 +// { dg-do compile { target c++14 } } + +template<typename F> void foo(F f) +{ + f(1); +} + +template<int> void bar() +{ + const int i = i; + foo([] (auto) { sizeof(i); }); +} + +void baz() { bar<1>(); }