📄 cp-init.c
字号:
for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases)) CLEAR_BINFO_BASEINIT_MARKED (vbases); /* Initialize all the virtual function table fields that do not come from virtual base classes. */ init_vfields (t, t, 0); if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (t)#ifdef SOS || TYPE_DYNAMIC (t)#endif ) expand_expr_stmt (build_virtual_init (TYPE_BINFO (t), t, current_class_decl)); /* Members we through expand_member_init. We initialize all the members needing initialization that did not get it so far. */ for (; current_member_init_list; current_member_init_list = TREE_CHAIN (current_member_init_list)) { tree name = TREE_PURPOSE (current_member_init_list); tree init = TREE_VALUE (current_member_init_list); tree field = (TREE_CODE (name) == COMPONENT_REF ? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name)); tree type; /* If one member shadows another, get the outermost one. */ if (TREE_CODE (field) == TREE_LIST) { field = TREE_VALUE (field); if (decl_type_context (field) != current_class_type) error ("field `%s' not in immediate context"); } type = TREE_TYPE (field); if (TREE_STATIC (field)) { error_with_aggr_type (DECL_FIELD_CONTEXT (field), "field `%s::%s' is static; only point of initialization is its declaration", IDENTIFIER_POINTER (name)); continue; } if (DECL_NAME (field)) { if (TREE_HAS_CONSTRUCTOR (field)) error ("multiple initializations given for member `%s'", IDENTIFIER_POINTER (DECL_NAME (field))); } /* Mark this node as having been initialized. */ TREE_HAS_CONSTRUCTOR (field) = 1; if (DECL_FIELD_CONTEXT (field) != t) fields_to_unmark = tree_cons (NULL_TREE, field, fields_to_unmark); if (TREE_CODE (name) == COMPONENT_REF) { /* Initialization of anonymous union. */ expand_assignment (name, init, 0, 0); continue; } decl = build_component_ref (C_C_D, name, 0, 1); if (TYPE_NEEDS_CONSTRUCTING (type)) { if (TREE_CODE (type) == ARRAY_TYPE && TREE_CHAIN (init) == NULL_TREE && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE) { /* Initialization of one array from another. */ expand_vec_init (TREE_OPERAND (decl, 1), decl, array_type_nelts (type), TREE_VALUE (init), 1); } else expand_aggr_init (decl, init, 0); } else { if (init == NULL_TREE) { error ("types without constructors must have complete initializers"); init = error_mark_node; } else if (TREE_CHAIN (init)) { warning ("initializer list treated as compound expression"); init = build_compound_expr (init); } else init = TREE_VALUE (init); expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); } if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type)) { cplus_expand_start_try (1); push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0)); } } for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) { /* All we care about is this unique member. It contains all the information we need to know, and that right early. */ tree type = TREE_TYPE (member); tree init = TREE_HAS_CONSTRUCTOR (member) ? error_mark_node : DECL_INITIAL (member); /* Unmark this field. If it is from an anonymous union, then unmark the field recursively. */ TREE_HAS_CONSTRUCTOR (member) = 0; if (TREE_ANON_UNION_ELEM (member)) emit_base_init (TREE_TYPE (member), 1); /* Member had explicit initializer. */ if (init == error_mark_node) continue; if (TREE_CODE (member) != FIELD_DECL) continue; if (type == error_mark_node) continue; if (TYPE_NEEDS_CONSTRUCTING (type)) { if (init) init = build_tree_list (NULL_TREE, init); decl = build_component_ref (C_C_D, DECL_NAME (member), 0, 0); expand_aggr_init (decl, init, 0); } else { if (init) { decl = build_component_ref (C_C_D, DECL_NAME (member), 0, 0); expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); } else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE) warning ("uninitialized reference member `%s'", IDENTIFIER_POINTER (DECL_NAME (member))); } if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type)) { cplus_expand_start_try (1); push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0)); } } /* Unmark fields which are initialized for the base class. */ while (fields_to_unmark) { TREE_HAS_CONSTRUCTOR (TREE_VALUE (fields_to_unmark)) = 0; fields_to_unmark = TREE_CHAIN (fields_to_unmark); } /* It is possible for the initializers to need cleanups. Expand those cleanups now that all the initialization has been done. */ expand_cleanups_to (NULL_TREE); if (! immediately) { extern rtx base_init_insns; do_pending_stack_adjust (); my_friendly_assert (base_init_insns == 0, 207); base_init_insns = get_insns (); end_sequence (); } /* All the implicit try blocks we built up will be zapped when we come to a real binding contour boundary. */}/* Check that all fields are properly initialized after an assignment to `this'. */voidcheck_base_init (t) tree t;{ tree member; for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) if (DECL_NAME (member) && TREE_USED (member)) error ("field `%s' used before initialized (after assignment to `this')", IDENTIFIER_POINTER (DECL_NAME (member)));}/* This code sets up the virtual function tables appropriate for the pointer DECL. It is a one-ply initialization. BINFO is the exact type that DECL is supposed to be. In multiple inheritance, this might mean "C's A" if C : A, B. */treebuild_virtual_init (main_binfo, binfo, decl) tree main_binfo, binfo; tree decl;{ tree type; tree vtbl, vtbl_ptr; tree vtype; if (TREE_CODE (binfo) == TREE_VEC) type = BINFO_TYPE (binfo); else if (TREE_CODE (binfo) == RECORD_TYPE) { type = binfo; binfo = TYPE_BINFO (type); } else my_friendly_abort (46); vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));#if 0 /* This code suggests that it's time to rewrite how we handle replicated baseclasses in G++. */ if (get_base_distance (vtype, TREE_TYPE (TREE_TYPE (decl)), 0, 0) == -2) { tree binfos = TYPE_BINFO_BASETYPES (TREE_TYPE (TREE_TYPE (decl))); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; tree result = NULL_TREE; for (i = n_baselinks-1; i >= 0; i--) { tree base_binfo = TREE_VEC_ELT (binfos, i); tree this_decl; if (get_base_distance (vtype, BINFO_TYPE (base_binfo), 0, 0) == -1) continue; if (TREE_VIA_VIRTUAL (base_binfo)) this_decl = build_vbase_pointer (build_indirect_ref (decl), BINFO_TYPE (base_binfo)); else if (BINFO_OFFSET_ZEROP (base_binfo)) this_decl = build1 (NOP_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), decl); else this_decl = build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), decl, BINFO_OFFSET (base_binfo)); result = tree_cons (NULL_TREE, build_virtual_init (main_binfo, base_binfo, this_decl), result); } return build_compound_expr (result); }#endif#ifdef SOS if (TYPE_DYNAMIC (type)) vtbl = build1 (NOP_EXPR, ptr_type_node, lookup_name (get_identifier (AUTO_VTABLE_NAME), 0)); else#endif {#if 1 vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), BINFO_TYPE (main_binfo), 0));#else my_friendly_assert (BINFO_TYPE (main_binfo) == BINFO_TYPE (binfo), 208); vtbl = BINFO_VTABLE (main_binfo);#endif /* 1 */ assemble_external (vtbl); TREE_USED (vtbl) = 1; vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl); } decl = convert_pointer_to (vtype, decl); vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, 0), vtype); if (vtbl_ptr == error_mark_node) return error_mark_node; /* Have to convert VTBL since array sizes may be different. */ return build_modify_expr (vtbl_ptr, NOP_EXPR, convert (TREE_TYPE (vtbl_ptr), vtbl));}/* Subroutine of `expand_aggr_vbase_init'. BINFO is the binfo of the type that is being initialized. INIT_LIST is the list of initializers for the virtual baseclass. */static voidexpand_aggr_vbase_init_1 (binfo, exp, addr, init_list) tree binfo, exp, addr, init_list;{ tree init = value_member (BINFO_TYPE (binfo), init_list); tree ref = build_indirect_ref (addr, 0); if (init) init = TREE_PURPOSE (init); /* Call constructors, but don't set up vtables. */ expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY); CLEAR_BINFO_VBASE_INIT_MARKED (binfo);}/* Initialize this object's virtual base class pointers. This must be done only at the top-level of the object being constructed. INIT_LIST is list of initialization for constructor to perform. */static voidexpand_aggr_vbase_init (binfo, exp, addr, init_list) tree binfo; tree exp; tree addr; tree init_list;{ tree type = BINFO_TYPE (binfo); if (TYPE_USES_VIRTUAL_BASECLASSES (type)) { tree result = init_vbase_pointers (type, addr); tree vbases; if (result) expand_expr_stmt (build_compound_expr (result)); /* Mark everything as having an initializer (either explicit or default). */ for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases)) SET_BINFO_VBASE_INIT_MARKED (vbases); /* First, initialize baseclasses which could be baseclasses for other virtual baseclasses. */ for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases)) /* Don't initialize twice. */ if (BINFO_VBASE_INIT_MARKED (vbases)) { tree tmp = result; while (BINFO_TYPE (vbases) != BINFO_TYPE (TREE_PURPOSE (tmp))) tmp = TREE_CHAIN (tmp); expand_aggr_vbase_init_1 (vbases, exp, TREE_OPERAND (TREE_VALUE (tmp), 0), init_list); } /* Now initialize the baseclasses which don't have virtual baseclasses. */ for (; result; result = TREE_CHAIN (result)) /* Don't initialize twice. */ if (BINFO_VBASE_INIT_MARKED (TREE_PURPOSE (result))) { my_friendly_abort (47); expand_aggr_vbase_init_1 (TREE_PURPOSE (result), exp, TREE_OPERAND (TREE_VALUE (result), 0), init_list); } }}/* Subroutine to perform parser actions for member initialization. S_ID is the scoped identifier. NAME is the name of the member. INIT is the initializer, or `void_type_node' if none. */voiddo_member_init (s_id, name, init) tree s_id, name, init;{ tree binfo, base; if (current_class_type == NULL_TREE || ! is_aggr_typedef (s_id, 1)) return; binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id), current_class_type, 1); if (binfo == error_mark_node) return; if (binfo == 0) { error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type); return; } base = convert_pointer_to (binfo, current_class_decl); expand_member_init (build_indirect_ref (base), name, init);}/* Function to give error message if member initialization specification is erroneous. FIELD is the member we decided to initialize. TYPE is the type for which the initialization is being performed. FIELD must be a member of TYPE, or the base type from which FIELD comes must not need a constructor. MEMBER_NAME is the name of the member. */static intmember_init_ok_or_else (field, type, member_name) tree field; tree type; char *member_name;{ if (field == error_mark_node) return 0; if (field == NULL_TREE) { error_with_aggr_type (type, "class `%s' does not have any field named `%s'", member_name); return 0; } if (DECL_CONTEXT (field) != type && TYPE_NEEDS_CONSTRUCTOR (DECL_CONTEXT (field))) { error ("member `%s' comes from base class needing constructor", member_name); return 0; } return 1;}/* If NAME is a viable field name for the aggregate DECL, and PARMS is a viable parameter list, then expand an _EXPR which describes this initialization. Note that we do not need to chase through the class's base classes to look for NAME, because if it's in that list, it will be handled by the constructor for that base class. We do not yet have a fixed-point finder to instantiate types being fed to overloaded constructors. If there is a unique constructor, then argument types can be got from that one. If INIT is non-NULL, then it the initialization should be placed in `current_base_init_list', where it will be processed by `emit_base_init'. */void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -