* [PATCH] Fix PR c++/64382
@ 2017-01-20 1:06 Adam Butcher
2017-01-26 20:14 ` Jason Merrill
0 siblings, 1 reply; 2+ messages in thread
From: Adam Butcher @ 2017-01-20 1:06 UTC (permalink / raw)
To: gcc-patches; +Cc: jason, nathan, adam
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
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] Fix PR c++/64382
2017-01-20 1:06 [PATCH] Fix PR c++/64382 Adam Butcher
@ 2017-01-26 20:14 ` Jason Merrill
0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2017-01-26 20:14 UTC (permalink / raw)
To: Adam Butcher; +Cc: gcc-patches List, nathan
On Wed, Jan 18, 2017 at 11:08 PM, Adam Butcher <adam@jessamine.co.uk> wrote:
> 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.
This is OK as a workaround. For GCC 8 I think we need to change how
we represent lambdas in templates: we shouldn't build up the closure
type at all until instantiation time, so we can do proper name
resolution (and to fix lambdas in pack expansions).
> 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).
The function looks pretty cheap, so I don't think caching it is necessary.
Jason
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-01-26 20:00 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-20 1:06 [PATCH] Fix PR c++/64382 Adam Butcher
2017-01-26 20:14 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).