diff options
author | Jason Merrill <jason@redhat.com> | 2013-03-16 22:35:18 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2013-03-16 22:35:18 -0400 |
commit | e2adfdad84167e48735d35154e0a8becf9264111 (patch) | |
tree | 4e7fde1281608a8010dea2b084852afa029f76a3 | |
parent | 5275b2c7d7c1ae888b1af5b6c86a96de032f12d8 (diff) | |
download | gcc-e2adfdad84167e48735d35154e0a8becf9264111.zip gcc-e2adfdad84167e48735d35154e0a8becf9264111.tar.gz gcc-e2adfdad84167e48735d35154e0a8becf9264111.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv8.C | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable2.C | 23 |
4 files changed, 59 insertions, 7 deletions
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 <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 * 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 <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>(); +} 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<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); +} |