📄 call.c
字号:
functions. */ if (TREE_CODE (type) == METHOD_TYPE) { tree addr; type = build_pointer_type (type); if (mark_addressable (function) == 0) return error_mark_node; addr = build1 (ADDR_EXPR, type, function); /* Address of a static or external variable or function counts as a constant */ if (staticp (function)) TREE_CONSTANT (addr) = 1; function = addr; } else function = default_conversion (function); return function;}/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or POINTER_TYPE to those. Note, pointer to member function types (TYPE_PTRMEMFUNC_P) must be handled by our callers. */treebuild_call (function, result_type, parms) tree function, result_type, parms;{ int is_constructor = 0; tree tmp; tree decl; function = build_addr_func (function); if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function))) { sorry ("unable to call pointer to member function here"); return error_mark_node; } if (TREE_CODE (function) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) decl = TREE_OPERAND (function, 0); else decl = NULL_TREE; if (decl && DECL_CONSTRUCTOR_P (decl)) is_constructor = 1; if (decl) my_friendly_assert (TREE_USED (decl), 990125); /* Don't pass empty class objects by value. This is useful for tags in STL, which are used to control overload resolution. We don't need to handle other cases of copying empty classes. */ if (! decl || ! DECL_BUILT_IN (decl)) for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp)) if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp))) && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp)))) { tree t = make_node (RTL_EXPR); TREE_TYPE (t) = TREE_TYPE (TREE_VALUE (tmp)); RTL_EXPR_RTL (t) = const0_rtx; RTL_EXPR_SEQUENCE (t) = NULL_RTX; TREE_VALUE (tmp) = build (COMPOUND_EXPR, TREE_TYPE (t), TREE_VALUE (tmp), t); } function = build_nt (CALL_EXPR, function, parms, NULL_TREE); TREE_HAS_CONSTRUCTOR (function) = is_constructor; TREE_TYPE (function) = result_type; TREE_SIDE_EFFECTS (function) = 1; return function;}/* Build something of the form ptr->method (args) or object.method (args). This can also build calls to constructors, and find friends. Member functions always take their class variable as a pointer. INSTANCE is a class instance. NAME is the name of the method desired, usually an IDENTIFIER_NODE. PARMS help to figure out what that NAME really refers to. BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE down to the real instance type to use for access checking. We need this information to get protected accesses correct. This parameter is used by build_member_call. FLAGS is the logical disjunction of zero or more LOOKUP_ flags. See cp-tree.h for more info. If this is all OK, calls build_function_call with the resolved member function. This function must also handle being called to perform initialization, promotion/coercion of arguments, and instantiation of default parameters. Note that NAME may refer to an instance variable name. If `operator()()' is defined for the type of that field, then we return that result. */treebuild_method_call (instance, name, parms, basetype_path, flags) tree instance, name, parms, basetype_path; int flags;{ tree basetype, instance_ptr;#ifdef GATHER_STATISTICS n_build_method_call++;#endif if (instance == error_mark_node || name == error_mark_node || parms == error_mark_node || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node)) return error_mark_node; if (processing_template_decl) { /* We need to process template parm names here so that tsubst catches them properly. Other type names can wait. */ if (TREE_CODE (name) == BIT_NOT_EXPR) { tree type = NULL_TREE; if (TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE) type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0); else if (TREE_CODE (TREE_OPERAND (name, 0)) == TYPE_DECL) type = TREE_TYPE (TREE_OPERAND (name, 0)); if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM) name = build_min_nt (BIT_NOT_EXPR, type); } return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE); } if (TREE_CODE (name) == BIT_NOT_EXPR) { if (parms) error ("destructors take no parameters"); basetype = TREE_TYPE (instance); if (TREE_CODE (basetype) == REFERENCE_TYPE) basetype = TREE_TYPE (basetype); if (! check_dtor_name (basetype, name)) cp_error ("destructor name `~%T' does not match type `%T' of expression", TREE_OPERAND (name, 0), basetype); if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype))) return cp_convert (void_type_node, instance); instance = default_conversion (instance); instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); return build_delete (build_pointer_type (basetype), instance_ptr, integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); } return build_new_method_call (instance, name, parms, basetype_path, flags);}/* New overloading code. */struct z_candidate { tree fn; tree convs; tree second_conv; int viable; tree basetype_path; tree template; tree warnings; struct z_candidate *next;};#define IDENTITY_RANK 0#define EXACT_RANK 1#define PROMO_RANK 2#define STD_RANK 3#define PBOOL_RANK 4#define USER_RANK 5#define ELLIPSIS_RANK 6#define BAD_RANK 7#define ICS_RANK(NODE) \ (ICS_BAD_FLAG (NODE) ? BAD_RANK \ : ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK \ : ICS_USER_FLAG (NODE) ? USER_RANK \ : ICS_STD_RANK (NODE))#define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE)#define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE)#define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)#define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)#define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)#define USER_CONV_CAND(NODE) \ ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)intnull_ptr_cst_p (t) tree t;{ if (t == null_node || (integer_zerop (t) && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)) return 1; return 0;}static treebuild_conv (code, type, from) enum tree_code code; tree type, from;{ tree t = build1 (code, type, from); int rank = ICS_STD_RANK (from); switch (code) { case PTR_CONV: case PMEM_CONV: case BASE_CONV: case STD_CONV: if (rank < STD_RANK) rank = STD_RANK; break; case QUAL_CONV: if (rank < EXACT_RANK) rank = EXACT_RANK; default: break; } ICS_STD_RANK (t) = rank; ICS_USER_FLAG (t) = ICS_USER_FLAG (from); ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from); return t;}static treenon_reference (t) tree t;{ if (TREE_CODE (t) == REFERENCE_TYPE) t = TREE_TYPE (t); return t;}static treestrip_top_quals (t) tree t;{ if (TREE_CODE (t) == ARRAY_TYPE) return t; return TYPE_MAIN_VARIANT (t);}/* Returns the standard conversion path (see [conv]) from type FROM to type TO, if any. For proper handling of null pointer constants, you must also pass the expression EXPR to convert from. */static treestandard_conversion (to, from, expr) tree to, from, expr;{ enum tree_code fcode, tcode; tree conv; int fromref = 0; if (TREE_CODE (to) == REFERENCE_TYPE) to = TREE_TYPE (to); if (TREE_CODE (from) == REFERENCE_TYPE) { fromref = 1; from = TREE_TYPE (from); } to = strip_top_quals (to); from = strip_top_quals (from); if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to)) && expr && type_unknown_p (expr)) { expr = instantiate_type (to, expr, 0); if (expr == error_mark_node) return NULL_TREE; from = TREE_TYPE (expr); } fcode = TREE_CODE (from); tcode = TREE_CODE (to); conv = build1 (IDENTITY_CONV, from, expr); if (fcode == FUNCTION_TYPE) { from = build_pointer_type (from); fcode = TREE_CODE (from); conv = build_conv (LVALUE_CONV, from, conv); } else if (fcode == ARRAY_TYPE) { from = build_pointer_type (TREE_TYPE (from)); fcode = TREE_CODE (from); conv = build_conv (LVALUE_CONV, from, conv); } else if (fromref || (expr && real_lvalue_p (expr))) conv = build_conv (RVALUE_CONV, from, conv); if (from == to) return conv; if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to)) && expr && null_ptr_cst_p (expr)) { conv = build_conv (STD_CONV, to, conv); } else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE) { enum tree_code ufcode = TREE_CODE (TREE_TYPE (from)); enum tree_code utcode = TREE_CODE (TREE_TYPE (to)); if (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (from)), TYPE_MAIN_VARIANT (TREE_TYPE (to)))) ; else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE && ufcode != FUNCTION_TYPE) { from = build_pointer_type (cp_build_qualified_type (void_type_node, CP_TYPE_QUALS (TREE_TYPE (from)))); conv = build_conv (PTR_CONV, from, conv); } else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE) { tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from)); tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to)); if (DERIVED_FROM_P (fbase, tbase) && (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))), TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to)))))) { from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from))); from = build_pointer_type (from); conv = build_conv (PMEM_CONV, from, conv); } } else if (IS_AGGR_TYPE (TREE_TYPE (from)) && IS_AGGR_TYPE (TREE_TYPE (to))) { if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from))) { from = cp_build_qualified_type (TREE_TYPE (to), CP_TYPE_QUALS (TREE_TYPE (from))); from = build_pointer_type (from); conv = build_conv (PTR_CONV, from, conv); } } if (same_type_p (from, to)) /* OK */; else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from))) conv = build_conv (QUAL_CONV, to, conv); else if (expr && string_conv_p (to, expr, 0)) /* converting from string constant to char *. */ conv = build_conv (QUAL_CONV, to, conv); else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from))) { conv = build_conv (PTR_CONV, to, conv); ICS_BAD_FLAG (conv) = 1; } else return 0; from = to; } else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from)) { tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from)); tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to)); tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn))); tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn))); if (! DERIVED_FROM_P (fbase, tbase) || ! same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn)) || ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)), TREE_CHAIN (TYPE_ARG_TYPES (tofn))) || CP_TYPE_QUALS (fbase) != CP_TYPE_QUALS (tbase)) return 0; from = cp_build_qualified_type (tbase, CP_TYPE_QUALS (fbase)); from = build_cplus_method_type (from, TREE_TYPE (fromfn), TREE_CHAIN (TYPE_ARG_TYPES (fromfn))); from = build_ptrmemfunc_type (build_pointer_type (from)); conv = build_conv (PMEM_CONV, from, conv); } else if (tcode == BOOLEAN_TYPE) { if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))) return 0; conv = build_conv (STD_CONV, to, conv); if (fcode == POINTER_TYPE || (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK)) ICS_STD_RANK (conv) = PBOOL_RANK; } /* We don't check for ENUMERAL_TYPE here because there are no standard conversions to enum type. */ else if (tcode == INTEGER_TYPE || tcode == BOOLEAN_TYPE || tcode == REAL_TYPE) { if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)) return 0; conv = build_conv (STD_CONV, to, conv); /* Give this a better rank if it's a promotion. */ if (to == type_promotes_to (from) && ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK) ICS_STD_RANK (conv) = PROMO_RANK; } else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) && DERIVED_FROM_P (to, from)) { if (TREE_CODE (conv) == RVALUE_CONV) conv = TREE_OPERAND (conv, 0); conv = build_conv (BASE_CONV, to, conv); } else return 0; return conv;}/* Returns the conversion path from type FROM to reference type TO for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -