This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/51459 (wrong code with lambda in template)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 08 Dec 2011 17:24:33 -0500
- Subject: C++ PATCH for c++/51459 (wrong code with lambda in template)
Here the problem was that we ended up inappropriately calling
cp_finish_decl on the capture proxies at instantiation time. Fixed by
handling them specially.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit ec77b5bed80dde351ee2086386f0c2282fdffa14
Author: Jason Merrill <jason@redhat.com>
Date: Thu Dec 8 14:01:45 2011 -0500
PR c++/51459
* pt.c (tsubst_expr) [DECL_EXPR]: Handle capture proxies properly.
* semantics.c (insert_capture_proxy): No longer static.
* cp-tree.h: Declare it.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index dccf485..87cb8b6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5593,6 +5593,7 @@ extern void apply_lambda_return_type (tree, tree);
extern tree add_capture (tree, tree, tree, bool, bool);
extern tree add_default_capture (tree, tree, tree);
extern tree build_capture_proxy (tree);
+extern void insert_capture_proxy (tree);
extern void insert_pending_capture_proxies (void);
extern bool is_capture_proxy (tree);
extern bool is_normal_capture_proxy (tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7603c11..296cd54 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12810,6 +12810,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
&& ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
/* Anonymous aggregates are a special case. */
finish_anon_union (decl);
+ else if (is_capture_proxy (DECL_EXPR_DECL (t)))
+ {
+ DECL_CONTEXT (decl) = current_function_decl;
+ insert_capture_proxy (decl);
+ }
else
{
int const_init = false;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 9a1043a..2dab6a7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8804,7 +8804,7 @@ is_normal_capture_proxy (tree decl)
/* VAR is a capture proxy created by build_capture_proxy; add it to the
current function, which is the operator() for the appropriate lambda. */
-static inline void
+void
insert_capture_proxy (tree var)
{
cp_binding_level *b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template4.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template4.C
new file mode 100644
index 0000000..a65727a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template4.C
@@ -0,0 +1,42 @@
+// PR c++/51459
+// { dg-do run { target c++11 } }
+
+struct func {
+ virtual ~func() { }
+ virtual void operator()() const = 0;
+ virtual func* clone() const = 0;
+};
+
+template<typename T>
+struct funcimpl : func {
+ explicit funcimpl(T t) : t(t) { }
+ void operator()() const { t(); }
+ func* clone() const { return new funcimpl(*this); }
+ T t;
+};
+
+struct function
+{
+ func* p;
+
+ template<typename T>
+ function(T t) : p(new funcimpl<T>(t)) { }
+
+ ~function() { delete p; }
+
+ function(const function& f) : p(f.p->clone()) { }
+
+ function& operator=(const function& ) = delete;
+
+ void operator()() const { (*p)(); }
+};
+
+template <typename F>
+function animate(F f) { return [=]{ f(); }; }
+
+int main()
+{
+ function linear1 = []{};
+ function av(animate(linear1));
+ av();
+}