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
This commit is contained in:
Adam Butcher 2017-01-27 07:59:06 +00:00 committed by Adam Butcher
parent 0fb9ec83c3
commit bb6a6ee9db
6 changed files with 73 additions and 3 deletions

View 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

View 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 */

View 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

View 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)))

View 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

View File

@ -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>;