aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-03-16 22:35:18 -0400
committerJason Merrill <jason@gcc.gnu.org>2013-03-16 22:35:18 -0400
commite2adfdad84167e48735d35154e0a8becf9264111 (patch)
tree4e7fde1281608a8010dea2b084852afa029f76a3 /gcc
parent5275b2c7d7c1ae888b1af5b6c86a96de032f12d8 (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv8.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mutable2.C23
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);
+}