📄 init.c
字号:
FLAGS is just passes to `build_method_call'. See that function for its description. */static voidexpand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags) tree binfo; tree true_exp, exp; tree init; int alias_this; int flags;{ tree type = TREE_TYPE (exp); tree init_type = NULL_TREE; my_friendly_assert (init != error_mark_node && type != error_mark_node, 211); /* Use a function returning the desired type to initialize EXP for us. If the function is a constructor, and its first argument is NULL_TREE, know that it was meant for us--just slide exp on in and expand the constructor. Constructors now come as TARGET_EXPRs. */ if (init) { tree init_list = NULL_TREE; if (TREE_CODE (init) == TREE_LIST) { init_list = init; if (TREE_CHAIN (init) == NULL_TREE) init = TREE_VALUE (init); } init_type = TREE_TYPE (init); if (TREE_CODE (init) != TREE_LIST) { if (TREE_CODE (init_type) == ERROR_MARK) return;#if 0 /* These lines are found troublesome 5/11/89. */ if (TREE_CODE (init_type) == REFERENCE_TYPE) init_type = TREE_TYPE (init_type);#endif /* This happens when we use C++'s functional cast notation. If the types match, then just use the TARGET_EXPR directly. Otherwise, we need to create the initializer separately from the object being initialized. */ if (TREE_CODE (init) == TARGET_EXPR) { if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type)) { if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == RESULT_DECL) /* Unify the initialization targets. */ DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp); else DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, 0, 0); expand_expr_stmt (init); return; } else { init = TREE_OPERAND (init, 1); init = build (CALL_EXPR, init_type, TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0); TREE_SIDE_EFFECTS (init) = 1; if (init_list) TREE_VALUE (init_list) = init; } } if (init_type == type && TREE_CODE (init) == CALL_EXPR#if 0 /* It is valid to directly initialize from a CALL_EXPR without going through X(X&), apparently. */ && ! TYPE_GETS_INIT_REF (type)#endif ) { /* A CALL_EXPR is a legitimate form of initialization, so we should not print this warning message. */#if 0 /* Should have gone away due to 5/11/89 change. */ if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE) init = convert_from_reference (init);#endif expand_assignment (exp, init, 0, 0); if (exp == DECL_RESULT (current_function_decl)) { /* Failing this assertion means that the return value from receives multiple initializations. */ my_friendly_assert (DECL_INITIAL (exp) == NULL_TREE || DECL_INITIAL (exp) == error_mark_node, 212); DECL_INITIAL (exp) = init; } return; } else if (init_type == type && TREE_CODE (init) == COND_EXPR) { /* Push value to be initialized into the cond, where possible. Avoid spurious warning messages when initializing the result of this function. */ TREE_OPERAND (init, 1) = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1)); if (exp == DECL_RESULT (current_function_decl)) DECL_INITIAL (exp) = NULL_TREE; TREE_OPERAND (init, 2) = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2)); if (exp == DECL_RESULT (current_function_decl)) DECL_INITIAL (exp) = init; TREE_SIDE_EFFECTS (init) = 1; expand_expr (init, const0_rtx, VOIDmode, 0); free_temp_slots (); return; } } /* We did not know what we were initializing before. Now we do. */ if (TREE_CODE (init) == TARGET_EXPR) { tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1); if (TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR && TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node) { /* In order for this to work for RESULT_DECLs, if their type has a constructor, then they must be BLKmode so that they will be meaningfully addressable. */ tree arg = build_unary_op (ADDR_EXPR, exp, 0); init = TREE_OPERAND (init, 1); init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)), TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0); TREE_SIDE_EFFECTS (init) = 1; TREE_VALUE (TREE_OPERAND (init, 1)) = convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg); if (alias_this) { expand_assignment (current_function_decl, init, 0, 0); return; } if (exp == DECL_RESULT (current_function_decl)) { if (DECL_INITIAL (DECL_RESULT (current_function_decl))) fatal ("return value from function receives multiple initializations"); DECL_INITIAL (exp) = init; } expand_expr_stmt (init); return; } } if (TREE_CODE (exp) == VAR_DECL && TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)) { tree t = store_init_value (exp, init); if (!t) { expand_decl_init (exp); return; } t = build (INIT_EXPR, type, exp, init); TREE_SIDE_EFFECTS (t) = 1; expand_expr_stmt (t); return; } /* Handle this case: when calling a constructor: xyzzy foo(bar); which really means: xyzzy foo = bar; Ugh! More useful for this case: xyzzy *foo = new xyzzy (bar); */ if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type)) { if (init_list && TREE_CHAIN (init_list)) { warning ("initializer list being treated as compound expression"); init = convert (type, build_compound_expr (init_list)); if (init == error_mark_node) return; } expand_assignment (exp, init, 0, 0); return; } /* See whether we can go through a type conversion operator. This wins over going through a non-existent constructor. If there is a constructor, it is ambiguous. */ if (TREE_CODE (init) != TREE_LIST) { tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE ? TREE_TYPE (init_type) : init_type; if (ttype != type && IS_AGGR_TYPE (ttype)) { tree rval = build_type_conversion (CONVERT_EXPR, type, init, 0); if (rval) { /* See if there is a constructor for``type'' that takes a ``ttype''-typed object. */ tree parms = build_tree_list (NULL_TREE, init); tree as_cons = NULL_TREE; if (TYPE_HAS_CONSTRUCTOR (type)) as_cons = build_method_call (exp, constructor_name_full (type), parms, binfo, LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION); if (as_cons != NULL_TREE && as_cons != error_mark_node) /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */ cp_error ("ambiguity between conversion to `%T' and constructor", type); else expand_assignment (exp, rval, 0, 0); return; } } } } /* Handle default copy constructors here, does not matter if there is a constructor or not. */ if (type == init_type && IS_AGGR_TYPE (type) && init && TREE_CODE (init) != TREE_LIST) expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags); /* Not sure why this is here... */ else if (TYPE_HAS_CONSTRUCTOR (type)) expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags); else if (TREE_CODE (type) == ARRAY_TYPE) { if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) expand_vec_init (exp, exp, array_type_nelts (type), init, 0); else if (TYPE_VIRTUAL_P (TREE_TYPE (type))) sorry ("arrays of objects with virtual functions but no constructors"); } else expand_recursive_init (binfo, true_exp, exp, init, CLASSTYPE_BASE_INIT_LIST (type), alias_this);}/* A pointer which holds the initializer. First call to expand_aggr_init gets this value pointed to, and sets it to init_null. */static tree *init_ptr, init_null;/* Subroutine of expand_recursive_init: ADDR is the address of the expression being initialized. INIT_LIST is the cons-list of initializations to be performed. ALIAS_THIS is its same, lovable self. */static voidexpand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this) tree binfo, true_exp, addr; tree init_list; int alias_this;{ while (init_list) { if (TREE_PURPOSE (init_list)) { if (TREE_CODE (TREE_PURPOSE (init_list)) == FIELD_DECL) { tree member = TREE_PURPOSE (init_list); tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), NULL_PTR); tree member_base = build (COMPONENT_REF, TREE_TYPE (member), subexp, member); if (IS_AGGR_TYPE (TREE_TYPE (member))) expand_aggr_init (member_base, DECL_INITIAL (member), 0, 0); else if (TREE_CODE (TREE_TYPE (member)) == ARRAY_TYPE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (member))) { member_base = save_expr (default_conversion (member_base)); expand_vec_init (member, member_base, array_type_nelts (TREE_TYPE (member)), DECL_INITIAL (member), 0); } else expand_expr_stmt (build_modify_expr (member_base, INIT_EXPR, DECL_INITIAL (member))); } else if (TREE_CODE (TREE_PURPOSE (init_list)) == TREE_LIST) { expand_recursive_init_1 (binfo, true_exp, addr, TREE_PURPOSE (init_list), alias_this); expand_recursive_init_1 (binfo, true_exp, addr, TREE_VALUE (init_list), alias_this); } else if (TREE_CODE (TREE_PURPOSE (init_list)) == ERROR_MARK) { /* Only initialize the virtual function tables if we are initializing the ultimate users of those vtables. */ if (TREE_VALUE (init_list)) { /* We have to ensure that the first argment to expand_virtual_init is in binfo's hierarchy. */ /* Is it the case that this is exactly the right binfo? */ /* If it is ok, then fixup expand_virtual_init, to make it much simpler. */ expand_virtual_init (get_binfo (TREE_VALUE (init_list), binfo, 0), addr); if (TREE_VALUE (init_list) == binfo && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))) expand_indirect_vtbls_init (binfo, true_exp, addr, 1); } } else my_friendly_abort (49); } else if (TREE_VALUE (init_list) && TREE_CODE (TREE_VALUE (init_list)) == TREE_VEC) { tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), NULL_PTR); expand_aggr_init_1 (binfo, true_exp, subexp, *init_ptr, alias_this && BINFO_OFFSET_ZEROP (TREE_VALUE (init_list)), LOOKUP_COMPLAIN); /* INIT_PTR is used up. */ init_ptr = &init_null; } else my_friendly_abort (50); init_list = TREE_CHAIN (init_list); }}/* Initialize EXP with INIT. Type EXP does not have a constructor, but it has a baseclass with a constructor or a virtual function table which needs initializing. INIT_LIST is a cons-list describing what parts of EXP actually need to be initialized. INIT is given to the *unique*, first constructor within INIT_LIST. If there are multiple first constructors, such as with multiple inheritance, INIT must be zero or an ambiguity error is reported. ALIAS_THIS is passed from `expand_aggr_init'. See comments there. */static voidexpand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this) tree binfo, true_exp, exp, init; tree init_list; int alias_this;{ tree *old_init_ptr = init_ptr; tree addr = build_unary_op (ADDR_EXPR, exp, 0); init_ptr = &init; if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))) { expand_aggr_vbase_init (binfo, exp, addr, init_list); expand_indirect_vtbls_init (binfo, true_exp, addr, 1); } expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this); if (*init_ptr) { tree type = TREE_TYPE (exp); if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); if (IS_AGGR_TYPE (type)) cp_error ("unexpected argument to constructor `%T'", type); else error ("unexpected argument to constructor"); } init_ptr = old_init_ptr;}/* Report an error if NAME is not the name of a user-defined, aggregate type. If OR_ELSE is nonzero, give an error message. */intis_aggr_typedef (name, or_else) tree name; int or_else;{ tree type; if (name == error_mark_node) return 0; if (IDENTIFIER_HAS_TYPE_VALUE (name)) type = IDENTIFIER_TYPE_VALUE (name); else { if (or_else) cp_error ("`%T' is not an aggregate typedef", name); return 0; } if (! IS_AGGR_TYPE (type) && TREE_CODE (type) != TEMPLATE_TYPE_PARM) { if (or_else) cp_error ("`%T' is not an aggregate type", type); return 0; } return 1;}/* Like is_aggr_typedef, but returns typedef if successful. */treeget_aggr_from_typedef (name, or_else) tree name; int or_else;{ tree type; if (name == error_mark_node) return NULL_TREE; if (IDENTIFIER_HAS_TYPE_VALUE (name)) type = IDENTIFIER_TYPE_VALUE (name); else { if (or_else) cp_error ("`%T' fails to be an aggregate typedef", name); return NULL_TREE; } if (! IS_AGGR_TYPE (type) && TREE_CODE (type) != TEMPLATE_TYPE_PARM) { if (or_else) cp_error ("type `%T' is of non-aggregate type", type); return NULL_TREE; } return type;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -