From: Momchil Velikov Date: Fri, 9 May 2014 20:07:45 +0000 (+0000) Subject: re PR c++/60463 (Lambda function can call a non-const member function with const... X-Git-Tag: upstream/12.2.0~63367 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0b360a07d3a45a1217ba68345601efcb6c118089;p=platform%2Fupstream%2Fgcc.git re PR c++/60463 (Lambda function can call a non-const member function with const this) PR c++/60463 PR c++/60755 * lambda.c (lambda_expr_this_capture): Add new parameter add_capture_p controlling whether the functions will try to capture 'this' via the default capture. (maybe_resolve_dummy): Likewise. * cp-tree.h: Adjust prototypes. * call.c, semantics.c: Change callers of these functions. * call.c (build_new_method_call_1): Use the actual 'this' that would be potentially captured for the overload resolution, instead of the dummy object. From-SVN: r210292 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ea813a9..5ddf555 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2014-05-09 Momchil Velikov + + PR c++/60463 + PR c++/60755 + * lambda.c (lambda_expr_this_capture): Add new parameter + add_capture_p controlling whether the functions will try to + capture 'this' via the default capture. + (maybe_resolve_dummy): Likewise. + * cp-tree.h: Adjust prototypes. + * call.c, semantics.c: Change callers of these functions. + * call.c (build_new_method_call_1): Use the actual 'this' that + would be potentially captured for the overload resolution, instead + of the dummy object. + 2014-05-09 Paolo Carlini * pt.c (convert_nontype_argument_function): Add tsubst_flags_t diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9e83c4a..254b43a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7760,7 +7760,11 @@ build_new_method_call_1 (tree instance, tree fns, vec **args, if (DECL_DESTRUCTOR_P (fn)) name = complete_dtor_identifier; - first_mem_arg = instance; + /* For the overload resolution we need to find the actual `this` + that would be captured if the call turns out to be to a + non-static member function. Do not actually capture it at this + point. */ + first_mem_arg = maybe_resolve_dummy (instance, false); /* Get the high-water mark for the CONVERSION_OBSTACK. */ p = conversion_obstack_alloc (0); @@ -7898,7 +7902,7 @@ build_new_method_call_1 (tree instance, tree fns, vec **args, && !DECL_CONSTRUCTOR_P (fn) && is_dummy_object (instance)) { - instance = maybe_resolve_dummy (instance); + instance = maybe_resolve_dummy (instance, true); if (instance == error_mark_node) call = error_mark_node; else if (!is_dummy_object (instance)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 34d3d20..ed8d099 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5890,8 +5890,8 @@ extern void insert_pending_capture_proxies (void); extern bool is_capture_proxy (tree); extern bool is_normal_capture_proxy (tree); extern void register_capture_members (tree); -extern tree lambda_expr_this_capture (tree); -extern tree maybe_resolve_dummy (tree); +extern tree lambda_expr_this_capture (tree, bool); +extern tree maybe_resolve_dummy (tree, bool); extern tree nonlambda_method_basetype (void); extern void maybe_add_lambda_conv_op (tree); extern bool is_lambda_ignored_entity (tree); diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 5ba6f14..3ce9ebb 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -624,11 +624,12 @@ add_default_capture (tree lambda_stack, tree id, tree initializer) return var; } -/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an - INDIRECT_REF, possibly adding it through default capturing. */ +/* Return the capture pertaining to a use of 'this' in LAMBDA, in the + form of an INDIRECT_REF, possibly adding it through default + capturing, if ADD_CAPTURE_P is false. */ tree -lambda_expr_this_capture (tree lambda) +lambda_expr_this_capture (tree lambda, bool add_capture_p) { tree result; @@ -648,7 +649,8 @@ lambda_expr_this_capture (tree lambda) /* Try to default capture 'this' if we can. */ if (!this_capture - && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE) + && (!add_capture_p + || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)) { tree lambda_stack = NULL_TREE; tree init = NULL_TREE; @@ -708,9 +710,14 @@ lambda_expr_this_capture (tree lambda) } if (init) - this_capture = add_default_capture (lambda_stack, - /*id=*/this_identifier, - init); + { + if (add_capture_p) + this_capture = add_default_capture (lambda_stack, + /*id=*/this_identifier, + init); + else + this_capture = init; + } } if (!this_capture) @@ -742,7 +749,7 @@ lambda_expr_this_capture (tree lambda) 'this' capture. */ tree -maybe_resolve_dummy (tree object) +maybe_resolve_dummy (tree object, bool add_capture_p) { if (!is_dummy_object (object)) return object; @@ -758,7 +765,7 @@ maybe_resolve_dummy (tree object) { /* In a lambda, need to go through 'this' capture. */ tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type); - tree cap = lambda_expr_this_capture (lam); + tree cap = lambda_expr_this_capture (lam, add_capture_p); object = build_x_indirect_ref (EXPR_LOCATION (object), cap, RO_NULL, tf_warning_or_error); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 4afb821..d925f5c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1675,7 +1675,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) object = maybe_dummy_object (scope, NULL); } - object = maybe_resolve_dummy (object); + object = maybe_resolve_dummy (object, true); if (object == error_mark_node) return error_mark_node; @@ -2434,7 +2434,7 @@ finish_this_expr (void) /* In a lambda expression, 'this' refers to the captured 'this'. */ if (LAMBDA_TYPE_P (type)) - result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type)); + result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type), true); else result = current_class_ptr; } diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C new file mode 100644 index 0000000..2de00d3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C @@ -0,0 +1,9 @@ +// PR c++/60463 +// PR c++/60755 +// { dg-do compile { target c++11 } } +struct S { + void f(); // { dg-message "no known conversion for implicit 'this' parameter from 'const S\\*' to 'S\\*'" } + void g() const { + [=] { f(); } (); // { dg-error "no matching function for call to 'S::f\\(\\)'" } + } +};