C++ PATCH for c++/79640, infinite recursion with generic lambda

Submitted by Jason Merrill on March 20, 2017, 6:30 p.m.

Details

Message ID CADzB+2n6Ec8+hW_ToGyC_Qzc=XU4JY8w50md-eXoDYHJW0bdPQ@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill March 20, 2017, 6:30 p.m.
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 <jason@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.

Patch hide | download patch | download mbox

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