aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Butcher <adam@jessamine.co.uk>2017-01-27 07:59:06 +0000
committerAdam Butcher <abutcher@gcc.gnu.org>2017-01-27 07:59:06 +0000
commitbb6a6ee9db925bea82bba47b1b3cdd3555fb539b (patch)
tree6d74a0c4c4c060c5f3cb24e32b23ffef3968df5b
parent0fb9ec83c38887a5b1da7376873506ae59b2c60e (diff)
downloadgcc-bb6a6ee9db925bea82bba47b1b3cdd3555fb539b.zip
gcc-bb6a6ee9db925bea82bba47b1b3cdd3555fb539b.tar.gz
gcc-bb6a6ee9db925bea82bba47b1b3cdd3555fb539b.tar.bz2
re PR c++/64382 (ICE due to use of `this` inside a lambda that captures everything by ref inside a member function of a class template)
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
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/parser.c27
-rw-r--r--gcc/cp/semantics.c10
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr64382.C23
6 files changed, 73 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 443df69..406d382 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f91b830..f412ddd 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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 */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9a61eb1..7f68550 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 6d5ea95..42b555c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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)))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0bf4dfb..71ef013 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..8f2e931
--- /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>;