From e2adfdad84167e48735d35154e0a8becf9264111 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 16 Mar 2013 22:35:18 -0400 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/pt.c | 22 ++++++++++++++------- gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv8.C | 15 ++++++++++++++ .../g++.dg/cpp0x/lambda/lambda-mutable2.C | 23 ++++++++++++++++++++++ 4 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv8.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 28b110c..59d6e8a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2013-03-16 Jason Merrill + 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 * method.c (walk_field_subobs): Disallow copy of rvalue ref. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6264add..126e110 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); if (decl) { 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); } else @@ -14470,12 +14484,6 @@ tsubst_copy_and_build (tree t, declaration of the op() for later calls to lambda_function. */ 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; RETURN (build_lambda_object (r)); diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv8.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv8.C new file mode 100644 index 0000000..abe272a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv8.C @@ -0,0 +1,15 @@ +// PR c++/56447 +// { dg-do compile { target c++11 } } + +template +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(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable2.C new file mode 100644 index 0000000..c54ff5c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable2.C @@ -0,0 +1,23 @@ +// PR c++/55532 +// { dg-do compile { target c++11 } } + +struct Foo { + void doit() { + } +}; + +template +void oops(Foo &foo, const T &) { + auto fun = [&] () mutable { + foo.doit(); + }; + auto fun2 = [=]() { + fun(); // { dg-error "" } + }; + fun2(); +} + +int main() { + Foo foo; + oops(foo, 1); +} -- 2.7.4