Commit e2adfdad by Jason Merrill Committed by Jason Merrill

re PR c++/56447 ([C++11] Lambda in template has conversion op it shouldn't have)

	PR c++/56447
	PR c++/55532
	* pt.c (instantiate_class_template_1): Instantiate lambda capture
	list here.
	(tsubst_copy_and_build): Not here.

From-SVN: r196729
parent 5275b2c7
2013-03-16 Jason Merrill <jason@redhat.com> 2013-03-16 Jason Merrill <jason@redhat.com>
PR c++/56447
PR c++/55532
* pt.c (instantiate_class_template_1): Instantiate lambda capture
list here.
(tsubst_copy_and_build): Not here.
PR c++/55017 PR c++/55017
* method.c (walk_field_subobs): Disallow copy of rvalue ref. * method.c (walk_field_subobs): Disallow copy of rvalue ref.
......
...@@ -8991,12 +8991,26 @@ instantiate_class_template_1 (tree type) ...@@ -8991,12 +8991,26 @@ instantiate_class_template_1 (tree type)
} }
} }
if (CLASSTYPE_LAMBDA_EXPR (type)) if (tree expr = CLASSTYPE_LAMBDA_EXPR (type))
{ {
tree decl = lambda_function (type); tree decl = lambda_function (type);
if (decl) if (decl)
{ {
instantiate_decl (decl, false, false); instantiate_decl (decl, false, false);
/* We need to instantiate the capture list from the template
after we've instantiated the closure members, but before we
consider adding the conversion op. Also keep any captures
that may have been added during instantiation of the op(). */
tree tmpl_expr = CLASSTYPE_LAMBDA_EXPR (pattern);
tree tmpl_cap
= tsubst_copy_and_build (LAMBDA_EXPR_CAPTURE_LIST (tmpl_expr),
args, tf_warning_or_error, NULL_TREE,
false, false);
LAMBDA_EXPR_CAPTURE_LIST (expr)
= chainon (tmpl_cap, nreverse (LAMBDA_EXPR_CAPTURE_LIST (expr)));
maybe_add_lambda_conv_op (type); maybe_add_lambda_conv_op (type);
} }
else else
...@@ -14470,12 +14484,6 @@ tsubst_copy_and_build (tree t, ...@@ -14470,12 +14484,6 @@ tsubst_copy_and_build (tree t,
declaration of the op() for later calls to lambda_function. */ declaration of the op() for later calls to lambda_function. */
complete_type (type); complete_type (type);
/* The capture list refers to closure members, so this needs to
wait until after we finish instantiating the type. Also keep
any captures that may have been added during instantiation. */
LAMBDA_EXPR_CAPTURE_LIST (r)
= chainon (RECUR (LAMBDA_EXPR_CAPTURE_LIST (t)),
LAMBDA_EXPR_CAPTURE_LIST (r));
LAMBDA_EXPR_THIS_CAPTURE (r) = NULL_TREE; LAMBDA_EXPR_THIS_CAPTURE (r) = NULL_TREE;
RETURN (build_lambda_object (r)); RETURN (build_lambda_object (r));
......
// PR c++/56447
// { dg-do compile { target c++11 } }
template <class T>
void f()
{
int i;
// This lambda should not have a conversion op, since it captures i
int (*p)() = [=]{ return i; }; // { dg-error "cannot convert" }
}
int main()
{
f<int>();
}
// PR c++/55532
// { dg-do compile { target c++11 } }
struct Foo {
void doit() {
}
};
template<typename T>
void oops(Foo &foo, const T &) {
auto fun = [&] () mutable {
foo.doit();
};
auto fun2 = [=]() {
fun(); // { dg-error "" }
};
fun2();
}
int main() {
Foo foo;
oops(foo, 1);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment