]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/51459 ('double free or corruption' involving std::function and lambdas)
authorJason Merrill <jason@redhat.com>
Thu, 8 Dec 2011 22:28:29 +0000 (17:28 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 8 Dec 2011 22:28:29 +0000 (17:28 -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.

From-SVN: r182141

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template4.C [new file with mode: 0644]

index ebb636e595986ecbb973b040a0a8c5a1f7a7f05b..70a93bd8df18bcd97beb1842ffe8e3c29dce8ef1 100644 (file)
@@ -1,3 +1,10 @@
+2011-12-08  Jason Merrill  <jason@redhat.com>
+
+       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.
+
 2011-12-07  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/51401
index dccf485a60fe5f64bec73dfbad930434b1cec85b..87cb8b6d04e508136f70a14552062277688d32d4 100644 (file)
@@ -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);
index 7603c1151e550867b53ab210eb116ee182e09e7c..296cd545794d09f90b53c9760a80dba2217177c1 100644 (file)
@@ -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;
index 9a1043a1a9b69c03484938656b2221c4a4cf7c74..2dab6a722a6e5bf9a85c0a4cf3dbe96473ae7664 100644 (file)
@@ -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;
index ed2428d8c16da931fa576313872bf0e2669dc633..5c97305a784d10bf8e2cf0c5e5b2a1aff1917968 100644 (file)
@@ -1,3 +1,8 @@
+2011-12-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51459
+       * g++.dg/cpp0x/lambda/lambda-template4.C: New.
+
 2011-12-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/51466
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 (file)
index 0000000..a65727a
--- /dev/null
@@ -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();
+}