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
This commit is contained in:
parent
91b67b5022
commit
0b360a07d3
@ -1,3 +1,17 @@
|
||||
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>
|
||||
|
||||
* 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,
|
||||
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<tree, va_gc> **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))
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
9
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C
Normal file
9
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const-this.C
Normal file
@ -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\\(\\)'" }
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user