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

📄 call.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* the base type of an instance variable is pointer to class */      basetype = TREE_TYPE (instance);      if (TREE_CODE (basetype) == REFERENCE_TYPE)	{	  basetype = TREE_TYPE (basetype);	  if (! IS_AGGR_TYPE (basetype))	    goto non_aggr_error;	  /* Call to convert not needed because we are remaining	     within the same type.  */	  instance_ptr = build1 (NOP_EXPR, build_pointer_type (basetype),				 instance);	  inst_ptr_basetype = TYPE_MAIN_VARIANT (basetype);	}      else	{	  if (! IS_AGGR_TYPE (basetype)	      && ! (TYPE_LANG_SPECIFIC (basetype)		    && (IS_SIGNATURE_POINTER (basetype)			|| IS_SIGNATURE_REFERENCE (basetype))))	    goto non_aggr_error;	  /* If `instance' is a signature pointer/reference and `name' is	     not a constructor, we are calling a signature member function.	     In that case set the `basetype' to the signature type.  */	  if ((IS_SIGNATURE_POINTER (basetype)	       || IS_SIGNATURE_REFERENCE (basetype))	      && TYPE_IDENTIFIER (basetype) != name)	    basetype = SIGNATURE_TYPE (basetype);	  if ((IS_SIGNATURE (basetype)	       && (instance_ptr = instance))	      || (lvalue_p (instance)		  && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0)))	      || (instance_ptr = unary_complex_lvalue (ADDR_EXPR, instance)))	    {	      if (instance_ptr == error_mark_node)		return error_mark_node;	    }	  else if (TREE_CODE (instance) == NOP_EXPR		   || TREE_CODE (instance) == CONSTRUCTOR)	    {	      /* A cast is not an lvalue.  Initialize a fresh temp		 with the value we are casting from, and proceed with		 that temporary.  We can't cast to a reference type,		 so that simplifies the initialization to something		 we can manage.  */	      tree temp = get_temp_name (TREE_TYPE (instance), 0);	      if (IS_AGGR_TYPE (TREE_TYPE (instance)))		expand_aggr_init (temp, instance, 0, flags);	      else		{		  store_init_value (temp, instance);		  expand_decl_init (temp);		}	      instance = temp;	      instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);	    }	  else	    {	      if (TREE_CODE (instance) != CALL_EXPR)		my_friendly_abort (125);	      if (TYPE_NEEDS_CONSTRUCTING (basetype))		instance = build_cplus_new (basetype, instance, 0);	      else		{		  instance = get_temp_name (basetype, 0);		  TREE_ADDRESSABLE (instance) = 1;		}	      instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);	    }	  /* @@ Should we call comp_target_types here?  */	  if (IS_SIGNATURE (basetype))	    inst_ptr_basetype = basetype;	  else	    inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr));	  if (TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (inst_ptr_basetype))	    basetype = inst_ptr_basetype;	  else	    {	      instance_ptr = convert (build_pointer_type (basetype), instance_ptr);	      if (instance_ptr == error_mark_node)		return error_mark_node;	    }	}      /* After converting `instance_ptr' above, `inst_ptr_basetype' was	 not updated, so we use `basetype' instead.  */      if (basetype_path == NULL_TREE	  && IS_SIGNATURE (basetype))	basetype_path = TYPE_BINFO (basetype);      else if (basetype_path == NULL_TREE ||	BINFO_TYPE (basetype_path) != TYPE_MAIN_VARIANT (inst_ptr_basetype))	basetype_path = TYPE_BINFO (inst_ptr_basetype);      result = build_field_call (basetype_path, instance_ptr, name, parms);      if (result)	return result;      if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))	{	  if (TREE_SIDE_EFFECTS (instance_ptr))	    {	      /* This action is needed because the instance is needed		 for providing the base of the virtual function table.		 Without using a SAVE_EXPR, the function we are building		 may be called twice, or side effects on the instance		 variable (such as a post-increment), may happen twice.  */	      instance_ptr = save_expr (instance_ptr);	      instance = build_indirect_ref (instance_ptr, NULL_PTR);	    }	  else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)	    {	      /* This happens when called for operator new ().  */	      instance = build_indirect_ref (instance, NULL_PTR);	    }	  need_vtbl = maybe_needed;	}    }  if (TYPE_SIZE (basetype) == 0)    {      /* This is worth complaining about, I think.  */      cp_error ("cannot lookup method in incomplete type `%T'", basetype);      return error_mark_node;    }  save_basetype = TYPE_MAIN_VARIANT (basetype);#if 0  if (all_virtual == 1      && (! strncmp (IDENTIFIER_POINTER (name), OPERATOR_METHOD_FORMAT,		     OPERATOR_METHOD_LENGTH)	  || instance_ptr == NULL_TREE	  || (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype) == 0)))    all_virtual = 0;#endif  last = NULL_TREE;  for (parmtypes = NULL_TREE, parm = parms; parm; parm = TREE_CHAIN (parm))    {      tree t = TREE_TYPE (TREE_VALUE (parm));      if (TREE_CODE (t) == OFFSET_TYPE)	{	  /* Convert OFFSET_TYPE entities to their normal selves.  */	  TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));	  t = TREE_TYPE (TREE_VALUE (parm));	}      if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF	  && TREE_CODE (t) == METHOD_TYPE)	{	  TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);	}#if 0      /* This breaks reference-to-array parameters.  */      if (TREE_CODE (t) == ARRAY_TYPE)	{	  /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.	     This eliminates needless calls to `compute_conversion_costs'.  */	  TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));	  t = TREE_TYPE (TREE_VALUE (parm));	}#endif      if (t == error_mark_node)	return error_mark_node;      last = build_tree_list (NULL_TREE, t);      parmtypes = chainon (parmtypes, last);    }  if (instance && IS_SIGNATURE (basetype))    {      /* @@ Should this be the constp/volatilep flags for the optr field	 of the signature pointer?  */      constp = TYPE_READONLY (basetype);      volatilep = TYPE_VOLATILE (basetype);      parms = tree_cons (NULL_TREE, instance_ptr, parms);    }  else if (instance)    {      /* TREE_READONLY (instance) fails for references.  */      constp = TYPE_READONLY (TREE_TYPE (TREE_TYPE (instance_ptr)));      volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (instance_ptr)));      parms = tree_cons (NULL_TREE, instance_ptr, parms);    }  else    {      /* Raw constructors are always in charge.  */      if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)	  && ! (flags & LOOKUP_HAS_IN_CHARGE))	{	  flags |= LOOKUP_HAS_IN_CHARGE;	  parms = tree_cons (NULL_TREE, integer_one_node, parms);	  parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);	}      constp = 0;      volatilep = 0;      instance_ptr = build_int_2 (0, 0);      TREE_TYPE (instance_ptr) = build_pointer_type (basetype);      parms = tree_cons (NULL_TREE, instance_ptr, parms);    }  parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);  if (last == NULL_TREE)    last = parmtypes;  /* Look up function name in the structure type definition.  */  if ((IDENTIFIER_HAS_TYPE_VALUE (name)       && ! IDENTIFIER_OPNAME_P (name)       && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name))       && TREE_CODE (IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE)      || name == constructor_name (basetype))    {      tree tmp = NULL_TREE;      if (IDENTIFIER_TYPE_VALUE (name) == basetype	  || name == constructor_name (basetype))	tmp = TYPE_BINFO (basetype);      else	tmp = get_binfo (IDENTIFIER_TYPE_VALUE (name), basetype, 0);            if (tmp != NULL_TREE)	{	  name_kind = "constructor";	  	  if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)	      && ! (flags & LOOKUP_HAS_IN_CHARGE))	    {	      /* Constructors called for initialization		 only are never in charge.  */	      tree tmplist;	      	      flags |= LOOKUP_HAS_IN_CHARGE;	      tmplist = tree_cons (NULL_TREE, integer_zero_node,				   TREE_CHAIN (parms));	      TREE_CHAIN (parms) = tmplist;	      tmplist = tree_cons (NULL_TREE, integer_type_node, TREE_CHAIN (parmtypes));	      TREE_CHAIN (parmtypes) = tmplist;	    }	  basetype = BINFO_TYPE (tmp);	}      else	name_kind = "method";    }  else    name_kind = "method";    if (basetype_path == NULL_TREE      || BINFO_TYPE (basetype_path) != TYPE_MAIN_VARIANT (basetype))    basetype_path = TYPE_BINFO (basetype);  result = lookup_fnfields (basetype_path, name,			    (flags & LOOKUP_COMPLAIN));  if (result == error_mark_node)    return error_mark_node;#if 0  /* Now, go look for this method name.  We do not find destructors here.     Putting `void_list_node' on the end of the parmtypes     fakes out `build_decl_overload' into doing the right thing.  */  TREE_CHAIN (last) = void_list_node;  method_name = build_decl_overload (name, parmtypes,				     1 + (name == constructor_name (save_basetype)					  || name == constructor_name_full (save_basetype)));  TREE_CHAIN (last) = NULL_TREE;#endif  for (pass = 0; pass < 2; pass++)    {      struct candidate *candidates;      struct candidate *cp;      int len;      unsigned best = 1;      /* This increments every time we go up the type hierarchy.	 The idea is to prefer a function of the derived class if possible. */      int b_or_d = 0;      baselink = result;      if (pass > 0)	{	  candidates	    = (struct candidate *) alloca ((ever_seen+1)					   * sizeof (struct candidate));	  bzero ((char *) candidates, (ever_seen + 1) * sizeof (struct candidate));	  cp = candidates;	  len = list_length (parms);	  ever_seen = 0;	  /* First see if a global function has a shot at it.  */	  if (flags & LOOKUP_GLOBAL)	    {	      tree friend_parms;	      tree parm = instance_ptr;	      if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)		parm = convert_from_reference (parm);	      else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)		parm = build_indirect_ref (parm, "friendifying parms (compiler error)");	      else		my_friendly_abort (167);	      friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));	      cp->h_len = len;	      cp->harshness = (struct harshness_code *)		alloca ((len + 1) * sizeof (struct harshness_code));	      result = build_overload_call (name, friend_parms, 0, cp);	      /* If it turns out to be the one we were actually looking for		 (it was probably a friend function), the return the		 good result.  */	      if (TREE_CODE (result) == CALL_EXPR)		return result;	      while ((cp->h.code & EVIL_CODE) == 0)		{		  /* non-standard uses: set the field to 0 to indicate		     we are using a non-member function.  */		  cp->u.field = 0;		  if (cp->harshness[len].distance == 0		      && cp->h.code < best)		    best = cp->h.code;		  cp += 1;		}	    }	}      while (baselink)	{	  /* We have a hit (of sorts). If the parameter list is	     "error_mark_node", or some variant thereof, it won't	     match any methods.  Since we have verified that the is	     some method vaguely matching this one (in name at least),	     silently return.	     	     Don't stop for friends, however.  */	  basetype_path = TREE_PURPOSE (baselink);	  function = TREE_VALUE (baselink);	  if (TREE_CODE (basetype_path) == TREE_LIST)	    basetype_path = TREE_VALUE (basetype_path);	  basetype = BINFO_TYPE (basetype_path);#if 0	  /* Cast the instance variable if necessary.  */	  if (basetype != TYPE_MAIN_VARIANT	      (TREE_TYPE (TREE_TYPE (TREE_VALUE (parms)))))	    {	      if (basetype == save_basetype)		TREE_VALUE (parms) = instance_ptr;	      else		{		  tree type = build_pointer_type		    (build_type_variant (basetype, constp, volatilep));		  TREE_VALUE (parms) = convert_force (type, instance_ptr, 0);		}	    }	  /* FIXME: this is the wrong place to get an error.  Hopefully	     the access-control rewrite will make this change more cleanly.  */	  if (TREE_VALUE (parms) == error_mark_node)	    return error_mark_node;#endif	  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))	    function = DECL_CHAIN (function);	  for (; function; function = DECL_CHAIN (function))	    {#ifdef GATHER_STATISTICS	      n_inner_fields_searched++;#endif	      ever_seen++;	      if (pass > 0)		found_fns = tree_cons (NULL_TREE, function, found_fns);	      /* Not looking for friends here.  */	      if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE		  && ! DECL_STATIC_FUNCTION_P (function))		continue;#if 0	      if (pass == 0		  && DECL_ASSEMBLER_NAME (function) == method_name)		goto found;#endif	      if (pass > 0)		{		  tree these_parms = parms;#ifdef GATHER_STATISTICS		  n_inner_fields_searched++;#endif		  cp->h_len = len;		  cp->harshness = (struct harshness_code *)		    alloca ((len + 1) * sizeof (struct harshness_code));		  if (DECL_STATIC_FUNCTION_P (function))		    these_parms = TREE_CHAIN (these_parms);		  compute_conversion_costs (function, these_parms, cp, len);		  if ((cp->h.code & EVIL_CODE) == 0)		    {		      cp->u.field = function;		      cp->function = function;		      cp->basetypes = basetype_path;		      /* Don't allow non-converting constructors to convert. */		      if (flags & LOOKUP_ONLYCONVERTING			  && DECL_LANG_SPECIFIC (function)			  && DECL_NONCONVERTING_P (function))			continue;		      /* No "two-level" conversions.  */		      if (flags & LOOKUP_NO_CONVERSION			  && (cp->h.code & USER_CODE))			continue;		      cp++;		    }		}	    }	  /* Now we have run through one link's member functions.	     arrange to head-insert this link's links.  */	  baselink = next_baselink (baselink);	  b_or_d += 1;	  /* Don't grab functions from base classes.  lookup_fnfield will	     do the work to get us down into the right place.  */	  baselink = NULL_TREE;	}      if (pass == 0)	{	  tree igv = lookup_name_nonclass (name);	  /* No exact match could be found.  Now try to find match	     using default conversions.  */	  if ((flags & LOOKUP_GLOBAL) && igv)	    {	      if (TREE_CODE (igv) == FUNCTION_DECL)		ever_seen += 1;	      else if (TREE_CODE (igv) == TREE_LIST)		ever_seen += count_functions (igv);	    }	  if (ever_seen == 0)	    {	      if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))		  == LOOKUP_SPECULATIVELY)	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -