Hi Jason,

I've reopened 64382 and unhooked it from 61636
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64382#c6).

This is a rebase of my original patch for 64382 from April 2015 against latest
master.

My query about caching parsing_default_capturing_generic_lambda_in_template()
still applies.  It is currently called once for each id-expression that is
dependent but its result will be consistent within a particular lambda body.
It feels like we should compute the state once when entering a lambda body and
refer to the cached state thereafter (resetting/restoring it on descent/return
from each lambda we come across).

Cheers,
Adam

        PR c++/64382
        * cp/parser.c (parsing_default_capturing_generic_lambda_in_template):
        New function.
        * cp/cp-tree.h: Declare it.
        * cp/semantics.c (finish_id_expression): Resolve names within a default
        capturing generic lambda defined within a template prior to
        instantiation to allow for captures to be added to the closure type.

        PR c++/64382
        * g++.dg/cpp1y/pr64382.C: New test.
---
 gcc/cp/cp-tree.h                     |  1 +
 gcc/cp/parser.c                      | 25 +++++++++++++++++++++++++
 gcc/cp/semantics.c                   |  8 +++++---
 gcc/testsuite/g++.dg/cpp1y/pr64382.C | 23 +++++++++++++++++++++++
 4 files changed, 54 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr64382.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9c4436710dd..77d20d4d3dc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6110,6 +6110,7 @@ extern bool maybe_clone_body                      (tree);
 /* In parser.c */
 extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool);
 extern bool parsing_nsdmi (void);
+extern bool parsing_default_capturing_generic_lambda_in_template (void);
 extern void inject_this_parameter (tree, cp_cv_quals);
 
 /* in pt.c */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 29dcfea283f..5cc0ddacc2b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -20450,6 +20450,31 @@ parsing_nsdmi (void)
   return false;
 }
 
+/* Return true iff our current scope is a default capturing generic lambda
+   defined within a template.  */
+
+bool
+parsing_default_capturing_generic_lambda_in_template (void)
+{
+  if (!processing_template_decl || !current_class_type)
+    return false;
+
+  tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type);
+  if (!lam || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) == CPLD_NONE)
+    return false;
+
+  tree callop = lambda_function (lam);
+  if (!callop)
+    return false;
+
+  return (DECL_TEMPLATE_INFO (callop)
+         && (DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop)
+         && ((current_nonlambda_class_type ()
+              && CLASSTYPE_TEMPLATE_INFO (current_nonlambda_class_type ()))
+             || ((current_nonlambda_function ()
+                  && DECL_TEMPLATE_INFO (current_nonlambda_function ())))));
+}
+
 /* Parse a late-specified return type, if any.  This is not a separate
    non-terminal, but part of a function declarator, which looks like
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 42024755e4f..3c0bd7e751c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3562,9 +3562,11 @@ finish_id_expression (tree id_expression,
                    ? CP_ID_KIND_UNQUALIFIED_DEPENDENT
                    : CP_ID_KIND_UNQUALIFIED)));
 
-      /* If the name was dependent on a template parameter, we will
-        resolve the name at instantiation time.  */
-      if (dependent_p)
+      /* If the name was dependent on a template parameter and we're not in a
+        default capturing generic lambda within a template, we will resolve the
+        name at instantiation time.  */
+      if (dependent_p
+         && !parsing_default_capturing_generic_lambda_in_template ())
        {
          if (DECL_P (decl)
              && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl)))
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr64382.C 
b/gcc/testsuite/g++.dg/cpp1y/pr64382.C
new file mode 100644
index 00000000000..8f2e931e048
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr64382.C
@@ -0,0 +1,23 @@
+// PR c++/64382
+// { dg-do compile { target c++14 } }
+
+template<typename T>
+struct my_queue
+{
+  void push(T)
+  {
+  }
+  void ice()
+  {
+    auto L = [=](auto &&v) {
+      push(v);
+    };
+    trav(L);
+  }
+  template<typename F>
+  void trav(F &&f)
+  {
+    f(T());
+  }
+};
+template struct my_queue<int>;
-- 
2.11.0

Reply via email to