📄 cp-typeck.c
字号:
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)); /* Handle methods, friends, and overloaded functions, respectively. */ if (is_method) { if (TREE_CODE (function) == FUNCTION_DECL) { if (DECL_NAME (function)) function = DECL_NAME (function); else function = TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function)); } else if (TREE_CODE (function) == TREE_LIST) {#if 0 if (TREE_CODE (TREE_VALUE (function)) == TREE_LIST) function = TREE_PURPOSE (TREE_VALUE (function)); else function = TREE_PURPOSE (function);#else my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312); function = TREE_PURPOSE (function);#endif } else if (TREE_CODE (function) != IDENTIFIER_NODE) { /* Call via a pointer to member function. */ if (decl == NULL_TREE) { error ("pointer to member function called, but not in class scope"); return error_mark_node; } if (TREE_CODE (TREE_TYPE (function)) != POINTER_TYPE) function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE, function); goto do_x_function; } /* this is an abbreviated method call. must go through here in case it is a virtual function. @@ Perhaps this could be optimized. */ if (decl == NULL_TREE) { if (current_class_type == NULL_TREE) { error ("object missing in call to method `%s'", IDENTIFIER_POINTER (function)); return error_mark_node; } /* Yow: call from a static member function. */ decl = build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), error_mark_node); } return build_method_call (decl, function, params, NULL_TREE, LOOKUP_NORMAL); } else if (TREE_CODE (function) == COMPONENT_REF && type == unknown_type_node) { function = TREE_PURPOSE (TREE_OPERAND (function, 1)); return build_method_call (decl, function, params, NULL_TREE, LOOKUP_NORMAL); } else if (TREE_CODE (function) == TREE_LIST) { if (TREE_CHAIN (function) != NULL_TREE) { if (TREE_CODE (TREE_VALUE (function)) == TEMPLATE_DECL) return build_overload_call_maybe (TREE_PURPOSE (function), params, 1, 0); else return build_overload_call (TREE_PURPOSE (function), params, 1, 0); } else if (TREE_VALUE (function) == NULL_TREE) { error ("function `%s' declared overloaded, but no definitions appear with which to resolve it", IDENTIFIER_POINTER (TREE_PURPOSE (function))); return error_mark_node; } else if (TREE_CODE (TREE_VALUE (function)) == TEMPLATE_DECL) return build_overload_call_maybe (TREE_PURPOSE (function), params, 1, 0); else function = TREE_VALUE (function); } else if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE && (TREE_CODE (function) == VAR_DECL || TREE_CODE (function) == PARM_DECL || TREE_CODE (function) == FIELD_DECL)) { error_with_decl (function, "call via pointer-to-member-function `%s' must be composed with object"); return error_mark_node; } do_x_function: if (TREE_CODE (function) == OFFSET_REF) { /* If the component is a data element (or a virtual function), we play games here to make things work. */ tree decl_addr; if (TREE_OPERAND (function, 0)) decl = TREE_OPERAND (function, 0); else decl = C_C_D; decl_addr = build_unary_op (ADDR_EXPR, decl, 0); function = get_member_function (&decl_addr, decl, TREE_OPERAND (function, 1)); params = tree_cons (NULL_TREE, decl_addr, params); return build_function_call (function, params); } type = TREE_TYPE (function); if (type != error_mark_node) { if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); if (TYPE_LANG_SPECIFIC (type) && TYPE_OVERLOADS_CALL_EXPR (type)) return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params); } if (is_method) { tree fntype = TREE_TYPE (function); tree ctypeptr; /* Explicitly named method? */ if (TREE_CODE (function) == FUNCTION_DECL) ctypeptr = TYPE_POINTER_TO (DECL_CLASS_CONTEXT (function)); /* Expression with ptr-to-method type? It could either be a plain usage, or it might be a case where the ptr-to-method is being passed in as an argument. */ else if (TREE_CODE (fntype) == POINTER_TYPE && (TREE_CODE_CLASS (TREE_CODE (function)) == 'e' || ((TREE_CODE_CLASS (TREE_CODE (function)) == 'd' || TREE_CODE_CLASS (TREE_CODE (function)) == 'r') && TREE_CODE (TREE_TYPE (fntype)) == METHOD_TYPE))) { tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)); ctypeptr = TYPE_POINTER_TO (rec); } /* Unexpected node type? */ else my_friendly_abort (116); if (decl == NULL_TREE) { if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) error ("invalid call to member function needing `this' in static member function scope"); else error ("pointer to member function called, but not in class scope"); return error_mark_node; } if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE) { decl = build_unary_op (ADDR_EXPR, decl, 0); decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl); } else decl = build_c_cast (ctypeptr, decl); params = tree_cons (NULL_TREE, decl, params); } return build_function_call (function, params);}treebuild_function_call_real (function, params, require_complete) tree function, params; int require_complete;{ register tree fntype, fndecl; register tree value_type; register tree coerced_params; int is_method; /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs, since FUNCTION is used in non-lvalue context. */ if (TREE_CODE (function) == NOP_EXPR && TREE_TYPE (function) == TREE_TYPE (TREE_OPERAND (function, 0))) function = TREE_OPERAND (function, 0); if (TREE_CODE (function) == FUNCTION_DECL) { GNU_xref_call (current_function_decl, IDENTIFIER_POINTER (DECL_NAME (function) ? DECL_NAME (function) : TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function)))); assemble_external (function); fndecl = function; /* Convert anything with function type to a pointer-to-function. */ if (pedantic && DECL_NAME (function) && IDENTIFIER_LENGTH (DECL_NAME (function)) == 4 && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (function)), "main") && DECL_CONTEXT (function) == NULL_TREE) { pedwarn ("ANSI C++ forbids calling `main' from within program"); } /* Differs from default_conversion by not setting TREE_ADDRESSABLE (because calling an inline function does not mean the function needs to be separately compiled). */ if (! DECL_INLINE (function)) { assemble_external (function); TREE_USED (function) = 1; } fntype = build_type_variant (TREE_TYPE (function), TREE_READONLY (function), TREE_THIS_VOLATILE (function)); function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); } else { fndecl = NULL_TREE; /* Convert anything with function type to a pointer-to-function. */ if (function == error_mark_node) return error_mark_node; function = default_conversion (function); } fntype = TREE_TYPE (function); is_method = (TREE_CODE (fntype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (fntype)) == METHOD_TYPE); if (!(TREE_CODE (fntype) == POINTER_TYPE && (TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE || is_method))) { error ("called object is not a function"); return error_mark_node; } /* fntype now gets the type of function pointed to. */ fntype = TREE_TYPE (fntype); /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype), params, fndecl, LOOKUP_NORMAL); /* Recognize certain built-in functions so we can make tree-codes other than CALL_EXPR. We do this when it enables fold-const.c to do something useful. */ if (TREE_CODE (function) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL && DECL_BUILT_IN (TREE_OPERAND (function, 0))) switch (DECL_FUNCTION_CODE (TREE_OPERAND (function, 0))) { case BUILT_IN_ABS: case BUILT_IN_LABS: case BUILT_IN_FABS: if (coerced_params == 0) return integer_zero_node; return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0); } /* C++ */ value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node; { register tree result = build (CALL_EXPR, value_type, function, coerced_params, NULL_TREE); TREE_SIDE_EFFECTS (result) = 1; TREE_RAISES (result) |= !! TYPE_RAISES_EXCEPTIONS (fntype); if (! require_complete) return result; if (value_type == void_type_node) return result; return require_complete_type (result); }}treebuild_function_call (function, params) tree function, params;{ return build_function_call_real (function, params, 1);} treebuild_function_call_maybe (function, params) tree function, params;{ return build_function_call_real (function, params, 0);}/* Convert the actual parameter expressions in the list VALUES to the types in the list TYPELIST. If parmdecls is exhausted, or when an element has NULL as its type, perform the default conversions. RETURN_LOC is the location of the return value, if known, NULL_TREE otherwise. This is useful in the case where we can avoid creating a temporary variable in the case where we can initialize the return value directly. If we are not eliding constructors, then we set this to NULL_TREE to avoid this avoidance. NAME is an IDENTIFIER_NODE or 0. It is used only for error messages. This is also where warnings about wrong number of args are generated. Return a list of expressions for the parameters as converted. Both VALUES and the returned value are chains of TREE_LIST nodes with the elements of the list in the TREE_VALUE slots of those nodes. In C++, unspecified trailing parameters can be filled in with their default arguments, if such were specified. Do so here. */treeconvert_arguments (return_loc, typelist, values, fndecl, flags) tree return_loc, typelist, values, fndecl; int flags;{ extern tree gc_protect_fndecl; register tree typetail, valtail; register tree result = NULL_TREE; char *called_thing; int maybe_raises = 0; int i = 0; if (! flag_elide_constructors) return_loc = 0; if (fndecl) { if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE) { if (DECL_NAME (fndecl) == NULL_TREE || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl))) called_thing = "constructor"; else called_thing = "member function"; i -= 1; } else { called_thing = "function"; } } for (valtail = values, typetail = typelist; valtail; valtail = TREE_CHAIN (valtail), i++) { register tree type = typetail ? TREE_VALUE (typetail) : 0; register tree val = TREE_VALUE (valtail); if (type == void_type_node) { if (fndecl) { char *buf = (char *)alloca (40 + strlen (called_thing)); sprintf (buf, "too many arguments to %s `%%s'", called_thing); error_with_decl (fndecl, buf); error ("at this point in file"); } else error ("too many arguments to function"); /* In case anybody wants to know if this argument list is valid. */ if (result) TREE_TYPE (tree_last (result)) = error_mark_node; break; } /* The tree type of the parameter being passed may not yet be known. In this case, its type is TYPE_UNKNOWN, and will be instantiated by the type given by TYPE. If TYPE is also NULL, the tree type of VAL is ERROR_MARK_NODE. */ if (type && type_unknown_p (val)) val = require_instantiated_type (type, val, integer_zero_node); else if (type_unknown_p (val)) { /* Strip the `&' from an overloaded FUNCTION_DECL. */ if (TREE_CODE (val) == ADDR_EXPR) val = TREE_OPERAND (val, 0); if (TREE_CODE (val) == TREE_LIST && TREE_CHAIN (val) == NULL_TREE && TREE_TYPE (TREE_VALUE (val)) != NULL_TREE && (TREE_TYPE (val) == unknown_type_node || DECL_CHAIN (TREE_VALUE (val)) == NULL_TREE)) /* Instantiates automatically. */ val = TREE_VALUE (val); else { error ("insufficient type information in parameter list"); val = integer_zero_node; } } else if (TREE_CODE (val) == OFFSET_REF) val = resolve_offset_ref (val); {#if 0 /* This code forces the assumption that if we have a ptr-to-func type in an arglist, that every routine that wants to check its validity has done so, and thus we need not do any more conversion. I don't remember why this is necessary. */ else if (TREE_CODE (ttype) == FUNCTION_TYPE && (type == NULL || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)) { type = build_pointer_type (ttype); }#endif } /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */ if (TREE_CODE (val) == NOP_EXPR && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0))) val = TREE_OPERAND (val, 0); if ((type == 0 || TREE_CODE (type) != REFERENCE_TYPE) && (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)) val = default_conversion (val); val = require_complete_type (val); if (val == error_mark_node) co
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -