⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 call.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 + -