📄 call.c
字号:
/* Functions related to invoking methods and overloaded functions. Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) and modified by Brendan Kehoe (brendan@cygnus.com).This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. *//* High-level class interface. */#include "config.h"#include "system.h"#include "tree.h"#include "cp-tree.h"#include "output.h"#include "flags.h"#include "rtl.h"#include "toplev.h"#include "obstack.h"#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freeextern int inhibit_warnings;extern tree ctor_label, dtor_label;static tree build_new_method_call PROTO((tree, tree, tree, tree, int));static tree build_field_call PROTO((tree, tree, tree, tree));static tree find_scoped_type PROTO((tree, tree, tree));static struct z_candidate * tourney PROTO((struct z_candidate *));static int joust PROTO((struct z_candidate *, struct z_candidate *, int));static int compare_ics PROTO((tree, tree));static tree build_over_call PROTO((struct z_candidate *, tree, int));static tree convert_like PROTO((tree, tree));static void op_error PROTO((enum tree_code, enum tree_code, tree, tree, tree, const char *));static tree build_object_call PROTO((tree, tree));static tree resolve_args PROTO((tree));static struct z_candidate * build_user_type_conversion_1 PROTO ((tree, tree, int));static void print_z_candidates PROTO((struct z_candidate *));static tree build_this PROTO((tree));static struct z_candidate * splice_viable PROTO((struct z_candidate *));static int any_viable PROTO((struct z_candidate *));static struct z_candidate * add_template_candidate PROTO((struct z_candidate *, tree, tree, tree, tree, int, unification_kind_t));static struct z_candidate * add_template_candidate_real PROTO((struct z_candidate *, tree, tree, tree, tree, int, tree, unification_kind_t));static struct z_candidate * add_template_conv_candidate PROTO((struct z_candidate *, tree, tree, tree, tree));static struct z_candidate * add_builtin_candidates PROTO((struct z_candidate *, enum tree_code, enum tree_code, tree, tree *, int));static struct z_candidate * add_builtin_candidate PROTO((struct z_candidate *, enum tree_code, enum tree_code, tree, tree, tree, tree *, tree *, int));static int is_complete PROTO((tree));static struct z_candidate * build_builtin_candidate PROTO((struct z_candidate *, tree, tree, tree, tree *, tree *, int));static struct z_candidate * add_conv_candidate PROTO((struct z_candidate *, tree, tree, tree));static struct z_candidate * add_function_candidate PROTO((struct z_candidate *, tree, tree, int));static tree implicit_conversion PROTO((tree, tree, tree, int));static tree standard_conversion PROTO((tree, tree, tree));static tree reference_binding PROTO((tree, tree, tree, int));static tree strip_top_quals PROTO((tree));static tree non_reference PROTO((tree));static tree build_conv PROTO((enum tree_code, tree, tree));static int is_subseq PROTO((tree, tree));static int maybe_handle_ref_bind PROTO((tree*, tree*));static void maybe_handle_implicit_object PROTO((tree*));static struct z_candidate * add_candidate PROTO((struct z_candidate *, tree, tree, int));static tree source_type PROTO((tree));static void add_warning PROTO((struct z_candidate *, struct z_candidate *));treebuild_vfield_ref (datum, type) tree datum, type;{ tree rval; if (datum == error_mark_node) return error_mark_node; if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE) datum = convert_from_reference (datum); if (! TYPE_USES_COMPLEX_INHERITANCE (type)) rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)), datum, CLASSTYPE_VFIELD (type)); else rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), NULL_TREE, 0); return rval;}/* Build a call to a member of an object. I.e., one that overloads operator ()(), or is a pointer-to-function or pointer-to-method. */static treebuild_field_call (basetype_path, instance_ptr, name, parms) tree basetype_path, instance_ptr, name, parms;{ tree field, instance; if (name == ctor_identifier || name == dtor_identifier) return NULL_TREE; /* Speed up the common case. */ if (instance_ptr == current_class_ptr && IDENTIFIER_CLASS_VALUE (name) == NULL_TREE) return NULL_TREE; field = lookup_field (basetype_path, name, 1, 0); if (field == error_mark_node || field == NULL_TREE) return field; if (TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL) { /* If it's a field, try overloading operator (), or calling if the field is a pointer-to-function. */ instance = build_indirect_ref (instance_ptr, NULL_PTR); instance = build_component_ref_1 (instance, field, 0); if (instance == error_mark_node) return error_mark_node; if (IS_AGGR_TYPE (TREE_TYPE (instance))) return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE); else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE) { if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE) return build_function_call (instance, parms); else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE) return build_function_call (instance, expr_tree_cons (NULL_TREE, instance_ptr, parms)); } } return NULL_TREE;}static treefind_scoped_type (type, inner_name, inner_types) tree type, inner_name, inner_types;{ tree tags = CLASSTYPE_TAGS (type); while (tags) { /* The TREE_PURPOSE of an enum tag (which becomes a member of the enclosing class) is set to the name for the enum type. So, if inner_name is `bar', and we strike `baz' for `enum bar { baz }', then this test will be true. */ if (TREE_PURPOSE (tags) == inner_name) { if (inner_types == NULL_TREE) return TYPE_MAIN_DECL (TREE_VALUE (tags)); return resolve_scope_to_name (TREE_VALUE (tags), inner_types); } tags = TREE_CHAIN (tags); } /* Look for a TYPE_DECL. */ for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags)) if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name) { /* Code by raeburn. */ if (inner_types == NULL_TREE) return tags; return resolve_scope_to_name (TREE_TYPE (tags), inner_types); } return NULL_TREE;}/* Resolve an expression NAME1::NAME2::...::NAMEn to the name that names the above nested type. INNER_TYPES is a chain of nested type names (held together by SCOPE_REFs); OUTER_TYPE is the type we know to enclose INNER_TYPES. Returns NULL_TREE if there is an error. */treeresolve_scope_to_name (outer_type, inner_stuff) tree outer_type, inner_stuff;{ register tree tmp; tree inner_name, inner_type; if (outer_type == NULL_TREE && current_class_type != NULL_TREE) { /* We first try to look for a nesting in our current class context, then try any enclosing classes. */ tree type = current_class_type; while (type && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)) { tree rval = resolve_scope_to_name (type, inner_stuff); if (rval != NULL_TREE) return rval; type = DECL_CONTEXT (TYPE_MAIN_DECL (type)); } } if (TREE_CODE (inner_stuff) == SCOPE_REF) { inner_name = TREE_OPERAND (inner_stuff, 0); inner_type = TREE_OPERAND (inner_stuff, 1); } else { inner_name = inner_stuff; inner_type = NULL_TREE; } if (outer_type == NULL_TREE) { tree x; /* If we have something that's already a type by itself, use that. */ if (IDENTIFIER_HAS_TYPE_VALUE (inner_name)) { if (inner_type) return resolve_scope_to_name (IDENTIFIER_TYPE_VALUE (inner_name), inner_type); return inner_name; } x = lookup_name (inner_name, 0); if (x && TREE_CODE (x) == NAMESPACE_DECL) { x = lookup_namespace_name (x, inner_type); return x; } return NULL_TREE; } if (! IS_AGGR_TYPE (outer_type)) return NULL_TREE; /* Look for member classes or enums. */ tmp = find_scoped_type (outer_type, inner_name, inner_type); /* If it's not a type in this class, then go down into the base classes and search there. */ if (! tmp && TYPE_BINFO (outer_type)) { tree binfos = TYPE_BINFO_BASETYPES (outer_type); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); tmp = resolve_scope_to_name (BINFO_TYPE (base_binfo), inner_stuff); if (tmp) return tmp; } tmp = NULL_TREE; } return tmp;}/* Returns nonzero iff the destructor name specified in NAME (a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many forms... */intcheck_dtor_name (basetype, name) tree basetype, name;{ name = TREE_OPERAND (name, 0); /* Just accept something we've already complained about. */ if (name == error_mark_node) return 1; if (TREE_CODE (name) == TYPE_DECL) name = TREE_TYPE (name); else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't') /* OK */; else if (TREE_CODE (name) == IDENTIFIER_NODE) { if ((IS_AGGR_TYPE (basetype) && name == constructor_name (basetype)) || (TREE_CODE (basetype) == ENUMERAL_TYPE && name == TYPE_IDENTIFIER (basetype))) name = basetype; else name = get_type_value (name); } else my_friendly_abort (980605); if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name)) return 1; return 0;}/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'. This is how virtual function calls are avoided. */treebuild_scoped_method_call (exp, basetype, name, parms) tree exp, basetype, name, parms;{ /* Because this syntactic form does not allow a pointer to a base class to be `stolen', we need not protect the derived->base conversion that happens here. @@ But we do have to check access privileges later. */ tree binfo, decl; tree type = TREE_TYPE (exp); if (type == error_mark_node || basetype == error_mark_node) return error_mark_node; if (processing_template_decl) { if (TREE_CODE (name) == BIT_NOT_EXPR && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE) { tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0); if (type) name = build_min_nt (BIT_NOT_EXPR, type); } name = build_min_nt (SCOPE_REF, basetype, name); return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE); } if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); if (TREE_CODE (basetype) == TREE_VEC) { binfo = basetype; basetype = BINFO_TYPE (binfo); } else binfo = NULL_TREE; /* Check the destructor call syntax. */ if (TREE_CODE (name) == BIT_NOT_EXPR) { /* We can get here if someone writes their destructor call like `obj.NS::~T()'; this isn't really a scoped method call, so hand it off. */ if (TREE_CODE (basetype) == NAMESPACE_DECL) return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL); if (! check_dtor_name (basetype, name)) cp_error ("qualified type `%T' does not match destructor name `~%T'", basetype, TREE_OPERAND (name, 0)); /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note that explicit ~int is caught in the parser; this deals with typedefs and template parms. */ if (! IS_AGGR_TYPE (basetype)) { if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype)) cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')", exp, basetype, type); return cp_convert (void_type_node, exp); } } if (! is_aggr_type (basetype, 1)) return error_mark_node; if (! IS_AGGR_TYPE (type)) { cp_error ("base object `%E' of scoped method call is of non-aggregate type `%T'", exp, type); return error_mark_node; } if (! binfo) { binfo = get_binfo (basetype, type, 1); if (binfo == error_mark_node) return error_mark_node; if (! binfo) error_not_base_type (basetype, type); } if (binfo) { if (TREE_CODE (exp) == INDIRECT_REF) decl = build_indirect_ref (convert_pointer_to_real (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR); else decl = build_scoped_ref (exp, basetype); /* Call to a destructor. */ if (TREE_CODE (name) == BIT_NOT_EXPR) { if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl))) return cp_convert (void_type_node, exp); return build_delete (TREE_TYPE (decl), decl, integer_two_node, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); } /* Call to a method. */ return build_method_call (decl, name, parms, binfo, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); } return error_mark_node;}/* We want the address of a function or method. We avoid creating a pointer-to-member function. */treebuild_addr_func (function) tree function;{ tree type = TREE_TYPE (function); /* We have to do these by hand to avoid real pointer to member
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -