From patchwork Thu Nov 29 20:12:19 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: C++ PATCH for c++/53137 ('this' capture in templates) X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 202820 Message-Id: <50B7C1A3.8040204@redhat.com> To: gcc-patches List Date: Thu, 29 Nov 2012 15:12:19 -0500 From: Jason Merrill List-Id: My earlier semi-fix for this issue failed to update LAMBDA_EXPR_THIS_CAPTURE to point to the proxy variable, so uses ended up with an unattached FIELD_DECL. Fixed thus. Tested x86_64-pc-linux-gnu, applying to trunk and 4.7. commit 73e140fd81aa10994184bb8edfe9cfafdc1499a9 Author: Jason Merrill Date: Thu Nov 29 11:37:05 2012 -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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 85c8e7c..ceac093 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ecb013e..3bc0d64 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 index 0000000..acf4eaa --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this6.C @@ -0,0 +1,32 @@ +// PR c++/53137 +// { dg-options -std=c++11 } + +template +void getParent(STORE& tStore) +{ +} + +struct Store +{ + template + void updateChildCommon(CheckParentFunc c) + { + c(); + } + + template + int& getStore(); + + template + void updateChild(const T& obj) + { + updateChildCommon([this] () { getParent(getStore()); }); + } + + void update(int obj); +}; + +void Store::update(int obj) +{ + updateChild(obj); +}