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

📄 call.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
  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_NAME (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;}/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.   This is how virtual function calls are avoided.  */treebuild_scoped_method_call (exp, scopes, name, parms)     tree exp, scopes, 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 basename = resolve_scope_to_name (NULL_TREE, scopes);  tree basetype, binfo, decl;  tree type = TREE_TYPE (exp);  if (type == error_mark_node      || basename == NULL_TREE)    return error_mark_node;  basetype = IDENTIFIER_TYPE_VALUE (basename);  if (TREE_CODE (type) == REFERENCE_TYPE)    type = TREE_TYPE (type);  /* 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 (TREE_CODE (name) == BIT_NOT_EXPR && ! is_aggr_typedef (basename, 0))    {      if (type != basetype)	cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",		  exp, basetype, type);      name = TREE_OPERAND (name, 0);      if (basetype != get_type_value (name))	cp_error ("qualified type `%T' does not match destructor name `~%T'",		  basetype, name);      return convert (void_type_node, exp);    }  if (! is_aggr_typedef (basename, 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_or_else (basetype, type)))    {      if (binfo == error_mark_node)	return error_mark_node;      if (TREE_CODE (exp) == INDIRECT_REF)	decl = build_indirect_ref (convert_pointer_to (binfo,						       build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR);      else	decl = build_scoped_ref (exp, scopes);      /* Call to a destructor.  */      if (TREE_CODE (name) == BIT_NOT_EXPR)	{	  /* Explicit call to destructor.  */	  name = TREE_OPERAND (name, 0);	  if (! (name == constructor_name (TREE_TYPE (decl))		 || TREE_TYPE (decl) == get_type_value (name)))	    {	      cp_error		("qualified type `%T' does not match destructor name `~%T'",		 TREE_TYPE (decl), name);	      return error_mark_node;	    }	  if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))	    return 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;}static voidprint_candidates (candidates)     tree candidates;{  cp_error_at ("candidates are: %D", TREE_VALUE (candidates));  candidates = TREE_CHAIN (candidates);  while (candidates)    {      cp_error_at ("                %D", TREE_VALUE (candidates));      candidates = TREE_CHAIN (candidates);    }}static voidprint_n_candidates (candidates, n)     struct candidate *candidates;     int n;{  int i;  cp_error_at ("candidates are: %D", candidates[0].function);  for (i = 1; i < n; i++)    cp_error_at ("                %D", candidates[i].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;{  register tree function, fntype, value_type;  register tree basetype, save_basetype;  register tree baselink, result, method_name, parmtypes, parm;  tree last;  int pass;  enum access_type access = access_public;  /* Range of cases for vtable optimization.  */  enum vtable_needs { not_needed, maybe_needed, unneeded, needed };  enum vtable_needs need_vtbl = not_needed;  char *name_kind;  int ever_seen = 0;  tree instance_ptr = NULL_TREE;  int all_virtual = flag_all_virtual;  int static_call_context = 0;  tree found_fns = NULL_TREE;  /* Keep track of `const' and `volatile' objects.  */  int constp, volatilep;#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;  /* This is the logic that magically deletes the second argument to     operator delete, if it is not needed. */  if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2)    {      tree save_last = TREE_CHAIN (parms);      tree result;      /* get rid of unneeded argument */      TREE_CHAIN (parms) = NULL_TREE;      result = build_method_call (instance, name, parms, basetype_path,				  (LOOKUP_SPECULATIVELY|flags)				  &~LOOKUP_COMPLAIN);      /* If it finds a match, return it. */      if (result)	return build_method_call (instance, name, parms, basetype_path, flags);      /* If it doesn't work, two argument delete must work */      TREE_CHAIN (parms) = save_last;    }  /* We already know whether it's needed or not for vec delete.  */  else if (name == ansi_opname[(int) VEC_DELETE_EXPR]	   && ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance)))    TREE_CHAIN (parms) = NULL_TREE;  if (TREE_CODE (name) == BIT_NOT_EXPR)    {      flags |= LOOKUP_DESTRUCTOR;      name = TREE_OPERAND (name, 0);      if (parms)	error ("destructors take no parameters");      basetype = TREE_TYPE (instance);      if (TREE_CODE (basetype) == REFERENCE_TYPE)	basetype = TREE_TYPE (basetype);      if (! ((IS_AGGR_TYPE (basetype)	      && name == constructor_name (basetype))	     || basetype == get_type_value (name)))	{	  cp_error ("destructor name `~%D' does not match type `%T' of expression",		    name, basetype);	  return convert (void_type_node, instance);	}      if (! TYPE_HAS_DESTRUCTOR (basetype))	return 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);    }  {    char *xref_name;        /* Initialize name for error reporting.  */    if (IDENTIFIER_OPNAME_P (name) && ! IDENTIFIER_TYPENAME_P (name))      {	char *p = operator_name_string (name);	xref_name = (char *)alloca (strlen (p) + 10);	sprintf (xref_name, "operator %s", p);      }    else if (TREE_CODE (name) == SCOPE_REF)      xref_name = IDENTIFIER_POINTER (TREE_OPERAND (name, 1));    else      xref_name = IDENTIFIER_POINTER (name);    GNU_xref_call (current_function_decl, xref_name);  }  if (instance == NULL_TREE)    {      basetype = NULL_TREE;      /* Check cases where this is really a call to raise	 an exception.  */      if (current_class_type && TREE_CODE (name) == IDENTIFIER_NODE)	{	  basetype = purpose_member (name, CLASSTYPE_TAGS (current_class_type));	  if (basetype)	    basetype = TREE_VALUE (basetype);	}      else if (TREE_CODE (name) == SCOPE_REF	       && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)	{	  if (! is_aggr_typedef (TREE_OPERAND (name, 0), 1))	    return error_mark_node;	  basetype = purpose_member (TREE_OPERAND (name, 1),				     CLASSTYPE_TAGS (IDENTIFIER_TYPE_VALUE (TREE_OPERAND (name, 0))));	  if (basetype)	    basetype = TREE_VALUE (basetype);	}      if (basetype != NULL_TREE)	;      /* call to a constructor... */      else if (basetype_path)	basetype = BINFO_TYPE (basetype_path);      else if (IDENTIFIER_HAS_TYPE_VALUE (name))	{	  basetype = IDENTIFIER_TYPE_VALUE (name);	  name = constructor_name_full (basetype);	}      else	{	  tree typedef_name = lookup_name (name, 1);	  if (typedef_name && TREE_CODE (typedef_name) == TYPE_DECL)	    {	      /* Canonicalize the typedef name.  */	      basetype = TREE_TYPE (typedef_name);	      name = TYPE_IDENTIFIER (basetype);	    }	  else	    {	      cp_error ("no constructor named `%T' in scope",			name);	      return error_mark_node;	    }	}      if (! IS_AGGR_TYPE (basetype))	{	non_aggr_error:	  if ((flags & LOOKUP_COMPLAIN) && TREE_CODE (basetype) != ERROR_MARK)	    cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",		      name, instance, basetype);	  return error_mark_node;	}    }  else if (instance == C_C_D || instance == current_class_decl)    {      /* When doing initialization, we side-effect the TREE_TYPE of	 C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE.  */      basetype = TREE_TYPE (C_C_D);      /* Anything manifestly `this' in constructors and destructors	 has a known type, so virtual function tables are not needed.  */      if (TYPE_VIRTUAL_P (basetype)	  && !(flags & LOOKUP_NONVIRTUAL))	need_vtbl = (dtor_label || ctor_label)	  ? unneeded : maybe_needed;      /* If `this' is a signature pointer and `name' is not a constructor,	 we are calling a signature member function.  In that case, set the	 `basetype' to the signature type and dereference the `optr' field.  */      if (IS_SIGNATURE_POINTER (basetype)	  && TYPE_IDENTIFIER (basetype) != name)	{	  basetype = SIGNATURE_TYPE (basetype);	  instance_ptr = build_optr_ref (instance);	  instance_ptr = convert (build_pointer_type (basetype), instance_ptr);	  basetype_path = TYPE_BINFO (basetype);	}      else	{	  instance = C_C_D;	  instance_ptr = current_class_decl;	  basetype_path = TYPE_BINFO (current_class_type);	}      result = build_field_call (basetype_path, instance_ptr, name, parms);      if (result)	return result;    }  else if (TREE_CODE (instance) == RESULT_DECL)    {      basetype = TREE_TYPE (instance);      /* Should we ever have to make a virtual function reference	 from a RESULT_DECL, know that it must be of fixed type	 within the scope of this function.  */      if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))	need_vtbl = maybe_needed;      instance_ptr = build1 (ADDR_EXPR, build_pointer_type (basetype), instance);    }  else    {      /* The MAIN_VARIANT of the type that `instance_ptr' winds up being.  */      tree inst_ptr_basetype;      static_call_context =	(TREE_CODE (instance) == INDIRECT_REF	 && TREE_CODE (TREE_OPERAND (instance, 0)) == NOP_EXPR	 && TREE_OPERAND (TREE_OPERAND (instance, 0), 0) == error_mark_node);      if (TREE_CODE (instance) == OFFSET_REF)	instance = resolve_offset_ref (instance);

⌨️ 快捷键说明

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