Here, we capture nf, then the use of the proxy decays to a constant during
semantic processing of +nf.  Since we saw some decay from proxy to constant,
we walk through the lambda body to see which proxies are still used, but we
weren't walking into subtrees of DECL_EXPR at all, so we missed the use of
&nf in the initializer of y, and removed the capture.  But then at
instantiation time we try to use nf, don't have a proxy anymore, and ICE.

Currently the template representation of +nf still uses the proxy rather than
the decayed constant; I will address that in a follow-up patch.

Tested x86_64-pc-linux-gnu, applying to trunk.

        * lambda.c (mark_const_cap_r): Do walk subtrees of DECL_EXPR for
        non-proxy decls.
---
 gcc/cp/lambda.c                                |  6 ++++--
 .../g++.dg/cpp1y/lambda-generic-const6.C       | 18 ++++++++++++++++++
 gcc/cp/ChangeLog                               |  6 ++++++
 3 files changed, 28 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-const6.C

diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 4b7a358a0ad..c31b06e2b1e 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -1488,8 +1488,10 @@ mark_const_cap_r (tree *t, int *walk_subtrees, void 
*data)
     {
       tree decl = DECL_EXPR_DECL (*t);
       if (is_constant_capture_proxy (decl))
-       var = DECL_CAPTURED_VARIABLE (decl);
-      *walk_subtrees = 0;
+       {
+         var = DECL_CAPTURED_VARIABLE (decl);
+         *walk_subtrees = 0;
+       }
     }
   else if (is_constant_capture_proxy (*t))
     var = DECL_CAPTURED_VARIABLE (*t);
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const6.C 
b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const6.C
new file mode 100644
index 00000000000..e85d6497488
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-const6.C
@@ -0,0 +1,18 @@
+// PR c++/88761
+// { dg-do compile { target c++14 } }
+
+template <class T>
+void f(T t) { t(1); }
+
+int main()
+{
+  const unsigned long nf = 10'000'000;
+
+  auto loop = [&](auto)
+  {
+    auto x = +nf;
+    auto y = &nf;
+  };
+
+  f(loop);
+}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f0545aee116..6c474fdda16 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2019-02-01  Jason Merrill  <ja...@redhat.com>
+
+       PR c++/88761 - ICE with reference capture of constant.
+       * lambda.c (mark_const_cap_r): Do walk subtrees of DECL_EXPR for
+       non-proxy decls.
+
 2019-02-01  Marek Polacek  <pola...@redhat.com>
 
        PR c++/88325 - ICE with invalid out-of-line template member definition.

base-commit: 5f6f6e51c0ff7f6e9e26f026e8ea856e0c4b91b5
-- 
2.20.1

Reply via email to