diff options
author | Nathan Sidwell <nathan@acm.org> | 2017-01-17 18:22:34 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2017-01-17 18:22:34 +0000 |
commit | 8ddfdbc265cfe0da5b727559d3736876d0198afb (patch) | |
tree | 127551e9b5d51e1763e5a76af78e43a959b28a43 /gcc/cp/lambda.c | |
parent | f46fe37e86aa04522258dad374d0c7bf9c443ed3 (diff) | |
download | gcc-8ddfdbc265cfe0da5b727559d3736876d0198afb.zip gcc-8ddfdbc265cfe0da5b727559d3736876d0198afb.tar.gz gcc-8ddfdbc265cfe0da5b727559d3736876d0198afb.tar.bz2 |
re PR c++/61636 (generic lambda: segfault / "cannot call member function without object")
PR c++/61636
* cp-tree.h (maybe_generic_this_capture): Declare.
* lambda.c (resolvable_dummy_lambda): New, broken out of ...
(maybe_resolve_dummy): ... here. Call it.
(maybe_generic_this_capture): New.
* parser.c (cp_parser_postfix_expression): Speculatively capture
this in generic lambda in unresolved member function call.
* pt.c (tsubst_copy_and_build): Force hard error from failed
member function lookup in generic lambda.
PR c++/61636
* g++.dg/cpp1y/pr61636-1.C: New.
* g++.dg/cpp1y/pr61636-2.C: New.
* g++.dg/cpp1y/pr61636-3.C: New.
From-SVN: r244544
Diffstat (limited to 'gcc/cp/lambda.c')
-rw-r--r-- | gcc/cp/lambda.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 98fdb74..4d22c3d 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -793,16 +793,14 @@ lambda_expr_this_capture (tree lambda, bool add_capture_p) return result; } -/* We don't want to capture 'this' until we know we need it, i.e. after - overload resolution has chosen a non-static member function. At that - point we call this function to turn a dummy object into a use of the - 'this' capture. */ +/* Return the current LAMBDA_EXPR, if this is a resolvable dummy + object. NULL otherwise.. */ -tree -maybe_resolve_dummy (tree object, bool add_capture_p) +static tree +resolvable_dummy_lambda (tree object) { if (!is_dummy_object (object)) - return object; + return NULL_TREE; tree type = TYPE_MAIN_VARIANT (TREE_TYPE (object)); gcc_assert (!TYPE_PTR_P (type)); @@ -812,18 +810,55 @@ maybe_resolve_dummy (tree object, bool add_capture_p) && LAMBDA_TYPE_P (current_class_type) && lambda_function (current_class_type) && DERIVED_FROM_P (type, current_nonlambda_class_type ())) - { - /* In a lambda, need to go through 'this' capture. */ - tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type); - tree cap = lambda_expr_this_capture (lam, add_capture_p); - if (cap && cap != error_mark_node) + return CLASSTYPE_LAMBDA_EXPR (current_class_type); + + return NULL_TREE; +} + +/* We don't want to capture 'this' until we know we need it, i.e. after + overload resolution has chosen a non-static member function. At that + point we call this function to turn a dummy object into a use of the + 'this' capture. */ + +tree +maybe_resolve_dummy (tree object, bool add_capture_p) +{ + if (tree lam = resolvable_dummy_lambda (object)) + if (tree cap = lambda_expr_this_capture (lam, add_capture_p)) + if (cap != error_mark_node) object = build_x_indirect_ref (EXPR_LOCATION (object), cap, RO_NULL, tf_warning_or_error); - } return object; } +/* When parsing a generic lambda containing an argument-dependent + member function call we defer overload resolution to instantiation + time. But we have to know now whether to capture this or not. + Do that if FNS contains any non-static fns. + The std doesn't anticipate this case, but I expect this to be the + outcome of discussion. */ + +void +maybe_generic_this_capture (tree object, tree fns) +{ + if (tree lam = resolvable_dummy_lambda (object)) + if (!LAMBDA_EXPR_THIS_CAPTURE (lam)) + { + /* We've not yet captured, so look at the function set of + interest. */ + if (BASELINK_P (fns)) + fns = BASELINK_FUNCTIONS (fns); + for (; fns; fns = OVL_NEXT (fns)) + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (OVL_CURRENT (fns))) + { + /* Found a non-static member. Capture this. */ + lambda_expr_this_capture (lam, true); + break; + } + } +} + /* Returns the innermost non-lambda function. */ tree |