static tree vla_capture_type (tree array_type) { static tree ptr_id, max_id; tree type = xref_tag (record_type, make_anon_name (), ts_current, false); xref_basetypes (type, NULL_TREE); type = begin_class_definition (type); if (!ptr_id) { ptr_id = get_identifier ("ptr"); max_id = get_identifier ("max"); } tree ptrtype = build_pointer_type (TREE_TYPE (array_type)); tree field = build_decl (input_location, FIELD_DECL, ptr_id, ptrtype); finish_member_declaration (field); field = build_decl (input_location, FIELD_DECL, max_id, sizetype); finish_member_declaration (field); return finish_struct (type, NULL_TREE); }
void register_capture_members (tree captures) { if (captures == NULL_TREE) return; register_capture_members (TREE_CHAIN (captures)); tree field = TREE_PURPOSE (captures); if (PACK_EXPANSION_P (field)) field = PACK_EXPANSION_PATTERN (field); /* We set this in add_capture to avoid duplicates. */ IDENTIFIER_MARKED (DECL_NAME (field)) = false; finish_member_declaration (field); }
tree objcp_finish_struct (tree t, tree fieldlist, tree attributes) { tree field, next_field; for (field = fieldlist; field; field = next_field) { next_field = TREE_CHAIN (field); /* insert one field at a time; */ TREE_CHAIN (field) = NULL_TREE; /* otherwise, grokfield croaks. */ finish_member_declaration (field); } t = finish_struct (t, attributes); pop_lang_context (); return t; }
tree objcp_finish_struct (location_t loc ATTRIBUTE_UNUSED, tree t, tree fieldlist, tree attributes) { tree field, next_field; for (field = fieldlist; field; field = next_field) { next_field = TREE_CHAIN (field); /* insert one field at a time; */ TREE_CHAIN (field) = NULL_TREE; /* otherwise, grokfield croaks. */ finish_member_declaration (field); } t = finish_struct (t, attributes); /* If we are inside an @interface and are generating the list of ivars, we need to check for duplicate ivars. */ if (fieldlist) objc_detect_field_duplicates (true); pop_lang_context (); return t; }
tree add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, bool explicit_init_p) { char *buf; tree type, member, name; bool vla = false; bool variadic = false; tree initializer = orig_init; if (PACK_EXPANSION_P (initializer)) { initializer = PACK_EXPANSION_PATTERN (initializer); variadic = true; } if (TREE_CODE (initializer) == TREE_LIST) initializer = build_x_compound_expr_from_list (initializer, ELK_INIT, tf_warning_or_error); type = TREE_TYPE (initializer); if (type == error_mark_node) return error_mark_node; if (array_of_runtime_bound_p (type)) { vla = true; if (!by_reference_p) error ("array of runtime bound cannot be captured by copy, " "only by reference"); /* For a VLA, we capture the address of the first element and the maximum index, and then reconstruct the VLA for the proxy. */ tree elt = cp_build_array_ref (input_location, initializer, integer_zero_node, tf_warning_or_error); initializer = build_constructor_va (init_list_type_node, 2, NULL_TREE, build_address (elt), NULL_TREE, array_type_nelts (type)); type = vla_capture_type (type); } else if (!dependent_type_p (type) && variably_modified_type_p (type, NULL_TREE)) { error ("capture of variable-size type %qT that is not an N3639 array " "of runtime bound", type); if (TREE_CODE (type) == ARRAY_TYPE && variably_modified_type_p (TREE_TYPE (type), NULL_TREE)) inform (input_location, "because the array element type %qT has " "variable size", TREE_TYPE (type)); type = error_mark_node; } else { type = lambda_capture_field_type (initializer, explicit_init_p); if (by_reference_p) { type = build_reference_type (type); if (!dependent_type_p (type) && !real_lvalue_p (initializer)) error ("cannot capture %qE by reference", initializer); } else { /* Capture by copy requires a complete type. */ type = complete_type (type); if (!dependent_type_p (type) && !COMPLETE_TYPE_P (type)) { error ("capture by copy of incomplete type %qT", type); cxx_incomplete_type_inform (type); return error_mark_node; } } } /* Add __ to the beginning of the field name so that user code won't find the field with name lookup. We can't just leave the name unset because template instantiation uses the name to find instantiated fields. */ buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3); buf[1] = buf[0] = '_'; memcpy (buf + 2, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id) + 1); name = get_identifier (buf); /* If TREE_TYPE isn't set, we're still in the introducer, so check for duplicates. */ if (!LAMBDA_EXPR_CLOSURE (lambda)) { if (IDENTIFIER_MARKED (name)) { pedwarn (input_location, 0, "already captured %qD in lambda expression", id); return NULL_TREE; } IDENTIFIER_MARKED (name) = true; } if (variadic) type = make_pack_expansion (type); /* Make member variable. */ member = build_decl (input_location, FIELD_DECL, name, type); DECL_VLA_CAPTURE_P (member) = vla; if (!explicit_init_p) /* Normal captures are invisible to name lookup but uses are replaced with references to the capture field; we implement this by only really making them invisible in unevaluated context; see qualify_lookup. For now, let's make explicitly initialized captures always visible. */ DECL_NORMAL_CAPTURE_P (member) = true; if (id == this_identifier) LAMBDA_EXPR_THIS_CAPTURE (lambda) = member; /* Add it to the appropriate closure class if we've started it. */ if (current_class_type && current_class_type == LAMBDA_EXPR_CLOSURE (lambda)) finish_member_declaration (member); tree listmem = member; if (variadic) { listmem = make_pack_expansion (member); initializer = orig_init; } LAMBDA_EXPR_CAPTURE_LIST (lambda) = tree_cons (listmem, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda)); if (LAMBDA_EXPR_CLOSURE (lambda)) return build_capture_proxy (member); /* For explicit captures we haven't started the function yet, so we wait and build the proxy from cp_parser_lambda_body. */ return NULL_TREE; }