tree add_default_capture (tree lambda_stack, tree id, tree initializer) { bool this_capture_p = (id == this_identifier); tree var = NULL_TREE; tree saved_class_type = current_class_type; tree node; for (node = lambda_stack; node; node = TREE_CHAIN (node)) { tree lambda = TREE_VALUE (node); current_class_type = LAMBDA_EXPR_CLOSURE (lambda); if (DECL_PACK_P (initializer)) initializer = make_pack_expansion (initializer); var = add_capture (lambda, id, initializer, /*by_reference_p=*/ (!this_capture_p && (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_REFERENCE)), /*explicit_init_p=*/false); initializer = convert_from_reference (var); } current_class_type = saved_class_type; return var; }
void cxx_print_lambda_node (FILE *file, tree node, int indent) { if (LAMBDA_EXPR_MUTABLE_P (node)) fprintf (file, " /mutable"); fprintf (file, " default_capture_mode=["); switch (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (node)) { case CPLD_NONE: fprintf (file, "NONE"); break; case CPLD_COPY: fprintf (file, "COPY"); break; case CPLD_REFERENCE: fprintf (file, "CPLD_REFERENCE"); break; default: fprintf (file, "??"); break; } fprintf (file, "] "); print_node (file, "capture_list", LAMBDA_EXPR_CAPTURE_LIST (node), indent + 4); print_node (file, "this_capture", LAMBDA_EXPR_THIS_CAPTURE (node), indent + 4); print_node (file, "return_type", LAMBDA_EXPR_RETURN_TYPE (node), indent + 4); print_node (file, "closure", LAMBDA_EXPR_CLOSURE (node), indent + 4); }
tree build_lambda_expr (void) { tree lambda = make_node (LAMBDA_EXPR); LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) = CPLD_NONE; LAMBDA_EXPR_CAPTURE_LIST (lambda) = NULL_TREE; LAMBDA_EXPR_THIS_CAPTURE (lambda) = NULL_TREE; LAMBDA_EXPR_PENDING_PROXIES (lambda) = NULL; LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE; LAMBDA_EXPR_MUTABLE_P (lambda) = false; return lambda; }
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; }