bool generic_lambda_fn_p (tree callop) { return (LAMBDA_FUNCTION_P (callop) && DECL_TEMPLATE_INFO (callop) && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (callop))); }
tree current_nonlambda_function (void) { tree fn = current_function_decl; while (fn && LAMBDA_FUNCTION_P (fn)) fn = decl_function_context (fn); return fn; }
bool is_capture_proxy (tree decl) { return (VAR_P (decl) && DECL_HAS_VALUE_EXPR_P (decl) && !DECL_ANON_UNION_VAR_P (decl) && LAMBDA_FUNCTION_P (DECL_CONTEXT (decl))); }
bool is_lambda_ignored_entity (tree val) { /* In unevaluated context, look past normal capture proxies. */ if (cp_unevaluated_operand && is_normal_capture_proxy (val)) return true; /* Always ignore lambda fields, their names are only for debugging. */ if (TREE_CODE (val) == FIELD_DECL && CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (val))) return true; /* None of the lookups that use qualify_lookup want the op() from the lambda; they want the one from the enclosing class. */ if (TREE_CODE (val) == FUNCTION_DECL && LAMBDA_FUNCTION_P (val)) return true; return false; }
void insert_pending_capture_proxies (void) { tree lam; vec<tree, va_gc> *proxies; unsigned i; if (!current_function_decl || !LAMBDA_FUNCTION_P (current_function_decl)) return; lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl)); proxies = LAMBDA_EXPR_PENDING_PROXIES (lam); for (i = 0; i < vec_safe_length (proxies); ++i) { tree var = (*proxies)[i]; insert_capture_proxy (var); } release_tree_vector (LAMBDA_EXPR_PENDING_PROXIES (lam)); LAMBDA_EXPR_PENDING_PROXIES (lam) = NULL; }
tree current_nonlambda_scope (void) { tree scope = current_scope (); for (;;) { if (TREE_CODE (scope) == FUNCTION_DECL && LAMBDA_FUNCTION_P (scope)) { scope = CP_TYPE_CONTEXT (DECL_CONTEXT (scope)); continue; } else if (LAMBDA_TYPE_P (scope)) { scope = CP_TYPE_CONTEXT (scope); continue; } break; } return scope; }
tree nonlambda_method_basetype (void) { tree fn, type; if (!current_class_ref) return NULL_TREE; type = current_class_type; if (!LAMBDA_TYPE_P (type)) return type; /* Find the nearest enclosing non-lambda function. */ fn = TYPE_NAME (type); do fn = decl_function_context (fn); while (fn && LAMBDA_FUNCTION_P (fn)); if (!fn || !DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) return NULL_TREE; return TYPE_METHOD_BASETYPE (TREE_TYPE (fn)); }
tree lambda_expr_this_capture (tree lambda, bool add_capture_p) { tree result; tree this_capture = LAMBDA_EXPR_THIS_CAPTURE (lambda); /* In unevaluated context this isn't an odr-use, so don't capture. */ if (cp_unevaluated_operand) add_capture_p = false; /* Try to default capture 'this' if we can. */ if (!this_capture && (!add_capture_p || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)) { tree lambda_stack = NULL_TREE; tree init = NULL_TREE; /* If we are in a lambda function, we can move out until we hit: 1. a non-lambda function or NSDMI, 2. a lambda function capturing 'this', or 3. a non-default capturing lambda function. */ for (tree tlambda = lambda; ;) { lambda_stack = tree_cons (NULL_TREE, tlambda, lambda_stack); if (LAMBDA_EXPR_EXTRA_SCOPE (tlambda) && TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (tlambda)) == FIELD_DECL) { /* In an NSDMI, we don't have a function to look up the decl in, but the fake 'this' pointer that we're using for parsing is in scope_chain. */ init = scope_chain->x_current_class_ptr; gcc_checking_assert (init && (TREE_TYPE (TREE_TYPE (init)) == current_nonlambda_class_type ())); break; } tree closure_decl = TYPE_NAME (LAMBDA_EXPR_CLOSURE (tlambda)); tree containing_function = decl_function_context (closure_decl); if (containing_function == NULL_TREE) /* We ran out of scopes; there's no 'this' to capture. */ break; if (!LAMBDA_FUNCTION_P (containing_function)) { /* We found a non-lambda function. */ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (containing_function)) /* First parameter is 'this'. */ init = DECL_ARGUMENTS (containing_function); break; } tlambda = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (containing_function)); if (LAMBDA_EXPR_THIS_CAPTURE (tlambda)) { /* An outer lambda has already captured 'this'. */ init = LAMBDA_EXPR_THIS_CAPTURE (tlambda); break; } if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (tlambda) == CPLD_NONE) /* An outer lambda won't let us capture 'this'. */ break; } if (init) { if (add_capture_p) this_capture = add_default_capture (lambda_stack, /*id=*/this_identifier, init); else this_capture = init; } } if (cp_unevaluated_operand) result = this_capture; else if (!this_capture) { if (add_capture_p) { error ("%<this%> was not captured for this lambda function"); result = error_mark_node; } else result = NULL_TREE; } else { /* To make sure that current_class_ref is for the lambda. */ gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == LAMBDA_EXPR_CLOSURE (lambda)); result = this_capture; /* If 'this' is captured, each use of 'this' is transformed into an access to the corresponding unnamed data member of the closure type cast (_expr.cast_ 5.4) to the type of 'this'. [ The cast ensures that the transformed expression is an rvalue. ] */ result = rvalue (result); } return result; }