Commit 0b360a07 by Momchil Velikov Committed by Jason Merrill

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
parent 91b67b50
2014-05-09 Momchil Velikov <momchil.velikov@gmail.com>
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 <paolo.carlini@oracle.com> 2014-05-09 Paolo Carlini <paolo.carlini@oracle.com>
* pt.c (convert_nontype_argument_function): Add tsubst_flags_t * pt.c (convert_nontype_argument_function): Add tsubst_flags_t
......
...@@ -7760,7 +7760,11 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, ...@@ -7760,7 +7760,11 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
if (DECL_DESTRUCTOR_P (fn)) if (DECL_DESTRUCTOR_P (fn))
name = complete_dtor_identifier; 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. */ /* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0); p = conversion_obstack_alloc (0);
...@@ -7898,7 +7902,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, ...@@ -7898,7 +7902,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
&& !DECL_CONSTRUCTOR_P (fn) && !DECL_CONSTRUCTOR_P (fn)
&& is_dummy_object (instance)) && is_dummy_object (instance))
{ {
instance = maybe_resolve_dummy (instance); instance = maybe_resolve_dummy (instance, true);
if (instance == error_mark_node) if (instance == error_mark_node)
call = error_mark_node; call = error_mark_node;
else if (!is_dummy_object (instance)) else if (!is_dummy_object (instance))
......
...@@ -5890,8 +5890,8 @@ extern void insert_pending_capture_proxies (void); ...@@ -5890,8 +5890,8 @@ extern void insert_pending_capture_proxies (void);
extern bool is_capture_proxy (tree); extern bool is_capture_proxy (tree);
extern bool is_normal_capture_proxy (tree); extern bool is_normal_capture_proxy (tree);
extern void register_capture_members (tree); extern void register_capture_members (tree);
extern tree lambda_expr_this_capture (tree); extern tree lambda_expr_this_capture (tree, bool);
extern tree maybe_resolve_dummy (tree); extern tree maybe_resolve_dummy (tree, bool);
extern tree nonlambda_method_basetype (void); extern tree nonlambda_method_basetype (void);
extern void maybe_add_lambda_conv_op (tree); extern void maybe_add_lambda_conv_op (tree);
extern bool is_lambda_ignored_entity (tree); extern bool is_lambda_ignored_entity (tree);
......
...@@ -624,11 +624,12 @@ add_default_capture (tree lambda_stack, tree id, tree initializer) ...@@ -624,11 +624,12 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
return var; return var;
} }
/* Return the capture pertaining to a use of 'this' in LAMBDA, in the form of an /* Return the capture pertaining to a use of 'this' in LAMBDA, in the
INDIRECT_REF, possibly adding it through default capturing. */ form of an INDIRECT_REF, possibly adding it through default
capturing, if ADD_CAPTURE_P is false. */
tree tree
lambda_expr_this_capture (tree lambda) lambda_expr_this_capture (tree lambda, bool add_capture_p)
{ {
tree result; tree result;
...@@ -648,7 +649,8 @@ lambda_expr_this_capture (tree lambda) ...@@ -648,7 +649,8 @@ lambda_expr_this_capture (tree lambda)
/* Try to default capture 'this' if we can. */ /* Try to default capture 'this' if we can. */
if (!this_capture 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 lambda_stack = NULL_TREE;
tree init = NULL_TREE; tree init = NULL_TREE;
...@@ -708,9 +710,14 @@ lambda_expr_this_capture (tree lambda) ...@@ -708,9 +710,14 @@ lambda_expr_this_capture (tree lambda)
} }
if (init) if (init)
{
if (add_capture_p)
this_capture = add_default_capture (lambda_stack, this_capture = add_default_capture (lambda_stack,
/*id=*/this_identifier, /*id=*/this_identifier,
init); init);
else
this_capture = init;
}
} }
if (!this_capture) if (!this_capture)
...@@ -742,7 +749,7 @@ lambda_expr_this_capture (tree lambda) ...@@ -742,7 +749,7 @@ lambda_expr_this_capture (tree lambda)
'this' capture. */ 'this' capture. */
tree tree
maybe_resolve_dummy (tree object) maybe_resolve_dummy (tree object, bool add_capture_p)
{ {
if (!is_dummy_object (object)) if (!is_dummy_object (object))
return object; return object;
...@@ -758,7 +765,7 @@ maybe_resolve_dummy (tree object) ...@@ -758,7 +765,7 @@ maybe_resolve_dummy (tree object)
{ {
/* In a lambda, need to go through 'this' capture. */ /* In a lambda, need to go through 'this' capture. */
tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type); 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, object = build_x_indirect_ref (EXPR_LOCATION (object), cap,
RO_NULL, tf_warning_or_error); RO_NULL, tf_warning_or_error);
} }
......
...@@ -1675,7 +1675,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) ...@@ -1675,7 +1675,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
object = maybe_dummy_object (scope, NULL); object = maybe_dummy_object (scope, NULL);
} }
object = maybe_resolve_dummy (object); object = maybe_resolve_dummy (object, true);
if (object == error_mark_node) if (object == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -2434,7 +2434,7 @@ finish_this_expr (void) ...@@ -2434,7 +2434,7 @@ finish_this_expr (void)
/* In a lambda expression, 'this' refers to the captured 'this'. */ /* In a lambda expression, 'this' refers to the captured 'this'. */
if (LAMBDA_TYPE_P (type)) 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 else
result = current_class_ptr; result = current_class_ptr;
} }
......
// 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\\(\\)'" }
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment