re PR c++/53137 (g++ segfault)
authorJason Merrill <jason@redhat.com>
Thu, 29 Nov 2012 20:12:58 +0000 (15:12 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 29 Nov 2012 20:12:58 +0000 (15:12 -0500)
PR c++/53137
* pt.c (tsubst_expr) [DECL_EXPR]: Set LAMBDA_EXPR_THIS_CAPTURE here.
(tsubst_copy_and_build) [LAMBDA_EXPR]: And clear it here.
(instantiate_class_template_1): Not here.

From-SVN: r193954

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

index d8d958a579cca2067b6d6f62eb5ba0bec987a9e2..60211d8add09aa65d89ef2b66f94166a89718246 100644 (file)
@@ -1,3 +1,10 @@
+2012-11-29  Jason Merrill  <jason@redhat.com>
+
+       PR c++/53137
+       * pt.c (tsubst_expr) [DECL_EXPR]: Set LAMBDA_EXPR_THIS_CAPTURE here.
+       (tsubst_copy_and_build) [LAMBDA_EXPR]: And clear it here.
+       (instantiate_class_template_1): Not here.
+
 2012-11-29  Marc Glisse  <marc.glisse@inria.fr>
 
        PR c++/53094
index 85c8e7c702cce3138b54d08c625d9f356edc1826..ceac093385da1f336e68e9965a3f396403253460 100644 (file)
@@ -659,8 +659,9 @@ enum cp_lambda_default_capture_mode_type {
 #define LAMBDA_EXPR_CAPTURE_LIST(NODE) \
   (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->capture_list)
 
-/* During parsing of the lambda, the node in the capture-list that holds
-   the 'this' capture.  */
+/* During parsing of the lambda-introducer, the node in the capture-list
+   that holds the 'this' capture.  During parsing of the body, the
+   capture proxy for that node.  */
 #define LAMBDA_EXPR_THIS_CAPTURE(NODE) \
   (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->this_capture)
 
index ecb013ecaee5dab46c76f81ec44b9facb63397d3..3bc0d64d6ba8abc9aea18986ea2fc7abfc5181af 100644 (file)
@@ -8956,14 +8956,8 @@ instantiate_class_template_1 (tree type)
       tree decl = lambda_function (type);
       if (decl)
        {
-         tree lam = CLASSTYPE_LAMBDA_EXPR (type);
-         LAMBDA_EXPR_THIS_CAPTURE (lam)
-           = lookup_field_1 (type, get_identifier ("__this"), false);
-
          instantiate_decl (decl, false, false);
          maybe_add_lambda_conv_op (type);
-
-         LAMBDA_EXPR_THIS_CAPTURE (lam) = NULL_TREE;
        }
       else
        gcc_assert (errorcount);
@@ -12728,6 +12722,12 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
                else if (is_capture_proxy (DECL_EXPR_DECL (t)))
                  {
                    DECL_CONTEXT (decl) = current_function_decl;
+                   if (DECL_NAME (decl) == this_identifier)
+                     {
+                       tree lam = DECL_CONTEXT (current_function_decl);
+                       lam = CLASSTYPE_LAMBDA_EXPR (lam);
+                       LAMBDA_EXPR_THIS_CAPTURE (lam) = decl;
+                     }
                    insert_capture_proxy (decl);
                  }
                else if (DECL_IMPLICIT_TYPEDEF_P (t))
@@ -14313,6 +14313,7 @@ tsubst_copy_and_build (tree t,
           wait until after we finish instantiating the type.  */
        LAMBDA_EXPR_CAPTURE_LIST (r)
          = RECUR (LAMBDA_EXPR_CAPTURE_LIST (t));
+       LAMBDA_EXPR_THIS_CAPTURE (r) = NULL_TREE;
 
        RETURN (build_lambda_object (r));
       }
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this6.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this6.C
new file mode 100644 (file)
index 0000000..acf4eaa
--- /dev/null
@@ -0,0 +1,32 @@
+// PR c++/53137
+// { dg-options -std=c++11 }
+
+template <typename STORE>
+void getParent(STORE& tStore)
+{
+}
+
+struct  Store
+{
+    template <typename CheckParentFunc>
+    void updateChildCommon(CheckParentFunc c)
+    {
+        c();
+    }
+
+    template <typename T>
+    int& getStore();
+
+    template <typename T>
+    void updateChild(const T& obj)
+    {
+        updateChildCommon([this] () { getParent(getStore<T>()); });
+    }
+
+    void update(int obj);
+};
+
+void Store::update(int obj)
+{
+    updateChild(obj);
+}