Patchwork C++ PATCH for c++/51459 (wrong code with lambda in template)

login
register
mail settings
Submitter Jason Merrill
Date Dec. 8, 2011, 10:24 p.m.
Message ID <4EE13921.4020705@redhat.com>
Download mbox | patch
Permalink /patch/130244/
State New
Headers show

Comments

Jason Merrill - Dec. 8, 2011, 10:24 p.m.
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.

Patch

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();
+}