re PR c++/64382 (ICE due to use of `this` inside a lambda that captures everything...
authorAdam Butcher <adam@jessamine.co.uk>
Fri, 27 Jan 2017 07:59:06 +0000 (07:59 +0000)
committerAdam Butcher <abutcher@gcc.gnu.org>
Fri, 27 Jan 2017 07:59:06 +0000 (07:59 +0000)
Fix PR c++/64382

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.

From-SVN: r244962

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/pr64382.C [new file with mode: 0644]

index 443df6980eaa485bb919d72198cddd68f1d2defe..406d382135f38570fe770c7143e81f236c1d4d4e 100644 (file)
@@ -1,3 +1,13 @@
+2017-01-27  Adam Butcher  <adam@jessamine.co.uk>
+
+       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.
+
 2017-01-26  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/68727
index f91b83027aa24be60fccf4da5b641b1005236715..f412ddd6e4aa2e80b703cf8ef421ee8e686a18fb 100644 (file)
@@ -6118,6 +6118,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 */
index 9a61eb1604bc387665e384baf9c898f89203ed58..7f685506bc176e2a528470459d2440e2b8d15e4a 100644 (file)
@@ -20454,6 +20454,33 @@ parsing_nsdmi (void)
   return false;
 }
 
+/* Return true iff our current scope is a default capturing generic lambda
+   defined within a template.  FIXME: This is part of a workaround (see
+   semantics.c) to handle building lambda closure types correctly in templates
+   which we ultimately want to defer to instantiation time. */
+
+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
 
index 6d5ea955db37eea1b785b8335872bf3804f1913e..42b555c5883304f0942830328683ddcb158f4eec 100644 (file)
@@ -3563,9 +3563,13 @@ 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.  FIXME: For lambdas, we should defer
+        building the closure type until instantiation time then we won't need
+        the extra test here.  */
+      if (dependent_p
+         && !parsing_default_capturing_generic_lambda_in_template ())
        {
          if (DECL_P (decl)
              && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl)))
index 0bf4dfb01eb002487f9f2c94e5cb1719bb6d0471..71ef013f098915d6d8f1184c6b54010bdb8cea32 100644 (file)
@@ -1,3 +1,8 @@
+2017-01-27  Adam Butcher  <adam@jessamine.co.uk>
+
+       PR c++/64382
+       * g++.dg/cpp1y/pr64382.C: New test.
+
 2017-01-26  Martin Sebor  <msebor@redhat.com>
 
        PR middle-end/78703
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr64382.C b/gcc/testsuite/g++.dg/cpp1y/pr64382.C
new file mode 100644 (file)
index 0000000..8f2e931
--- /dev/null
@@ -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>;