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>(); }

Reply via email to