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

📄 cp-call.c

📁 早期freebsd实现
💻 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_types)     tree outer_type, inner_types;{  register tree tmp;  tree tags, inner_name;  if (outer_type == NULL_TREE && current_class_type != NULL_TREE)    {      /* We first try to look for a nesting in our current class context.  */      tree rval = resolve_scope_to_name (current_class_type, inner_types);      if (rval != NULL_TREE)	return rval;    }  if (TREE_CODE (inner_types) == SCOPE_REF)    {      inner_name = TREE_OPERAND (inner_types, 0);      inner_types = TREE_OPERAND (inner_types, 1);    }  else    {      inner_name = inner_types;      inner_types = 0;    }  if (outer_type == NULL_TREE)    {      /* If we have something that's already a type by itself,	 use that.  */      if (IDENTIFIER_HAS_TYPE_VALUE (inner_name))	{	  if (inner_types)	    return resolve_scope_to_name (IDENTIFIER_TYPE_VALUE (inner_name),					  inner_types);	  return inner_name;	}      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_types);  /* 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 = find_scoped_type (BINFO_TYPE (base_binfo),				  inner_name, inner_types);	  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;     tree scopes;     tree name;     tree 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 visibility 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      || ! is_aggr_typedef (basename, 1))    return error_mark_node;  if (! IS_AGGR_TYPE (type))    {      error ("base object of scoped method call is not of aggregate type");      return error_mark_node;    }  basetype = IDENTIFIER_TYPE_VALUE (basename);  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)), 0);      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 (! is_aggr_typedef (name, 1))	    return error_mark_node;	  if (TREE_TYPE (decl) != IDENTIFIER_TYPE_VALUE (name))	    {	      error_with_aggr_type (TREE_TYPE (decl),				    "qualified type `%s' does not match destructor type `%s'",				    IDENTIFIER_POINTER (name));	      return error_mark_node;	    }	  if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))	    error_with_aggr_type (TREE_TYPE (decl), "type `%s' has no destructor");	  return build_delete (TREE_TYPE (decl), decl, integer_two_node,			       LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,			       0, 0);	}      /* Call to a method.  */      return build_method_call (decl, name, parms, NULL_TREE,				LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);    }  return error_mark_node;}/* 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 field of the struct, union, or class   whose type is that of INSTANCE.   PARMS help to figure out what that NAME really refers to.   BASETYPE_PATH, if non-NULL, tells which basetypes of INSTANCE   we should be traversed before starting our search.  We need   this information to get protected accesses correct.   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 visibility_type visibility;  int rank_for_overload ();  /* Range of cases for vtable optimization.  */  enum vtable_needs    {      not_needed, maybe_needed, unneeded, needed,    };  enum vtable_needs need_vtbl = not_needed;  char *err_name;  char *name_kind;  int ever_seen = 0;  tree instance_ptr = NULL_TREE;  int all_virtual = flag_all_virtual;  int static_call_context = 0;  tree saw_private = 0;  tree saw_protected = 0;#ifdef SOS  /* If call is a call to a constructor, then `dtbl'     will first be initialized with the function table pointer     of the appropriate type (calling "sosFindCode" as a last     resort), the the call to the constructor will go through there.  */  tree dtbl = (flags & LOOKUP_DYNAMIC) ? TREE_VALUE (parms) : NULL_TREE;  /* Flag saying whether or not `dtbl' has been inserted into the     parameter list.  This is needed because we cannot tell (until     we have a match) whether this parameter should go in or not.     If 1, then `dtbl' is living naturally.     If 0, then `dtbl' is not among the parms that we know about.     If -1, the `dtbl' was place into the parms unnaturally.     Note that we may side-effect the parameter list, but in such a way     that the caller of this function would never know.  */  int dtbl_inserted = (flags & LOOKUP_DYNAMIC);#endif  /* 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 != 0 && 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 works, return it. */      if (result && result != error_mark_node)	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;    }#if 0  /* C++ 2.1 does not allow this, but ANSI probably will.  */  if (TREE_CODE (name) == BIT_NOT_EXPR)    {      error ("invalid call to destructor, use qualified name `%s::~%s'",	     IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (name));      return error_mark_node;    }#else  if (TREE_CODE (name) == BIT_NOT_EXPR)    {      flags |= LOOKUP_DESTRUCTOR;      name = TREE_OPERAND (name, 0);      if (! is_aggr_typedef (name, 1))	return error_mark_node;      if (parms)	error ("destructors take no parameters");      basetype = IDENTIFIER_TYPE_VALUE (name);      if (! TYPE_HAS_DESTRUCTOR (basetype))	{#if 0 /* ARM says tp->~T() without T::~T() is valid.  */	  error_with_aggr_type (basetype, "type `%s' has no destructor");#endif	  /* A destructive destructor wouldn't be a bad idea, but let's	     not bother for now.  */	  return build_c_cast (void_type_node, instance);	}      instance = default_conversion (instance);      if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)	instance_ptr = instance;      else	instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);      return build_delete (basetype, instance_ptr, integer_two_node,			   LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0, 0);    }#endif  /* Initialize name for error reporting.  */  if (IDENTIFIER_TYPENAME_P (name))    err_name = "type conversion operator";  else if (IDENTIFIER_OPNAME_P (name))    {      char *p = operator_name_string (name);      err_name = (char *)alloca (strlen (p) + 10);      sprintf (err_name, "operator %s", p);    }  else if (TREE_CODE (name) == SCOPE_REF)    err_name = IDENTIFIER_POINTER (TREE_OPERAND (name, 1));  else    err_name = IDENTIFIER_POINTER (name);  if (IDENTIFIER_OPNAME_P (name))    GNU_xref_call (current_function_decl,  IDENTIFIER_POINTER (name));  else    GNU_xref_call (current_function_decl, err_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 (IDENTIFIER_HAS_TYPE_VALUE (name))	{	  basetype = IDENTIFIER_TYPE_VALUE (name);	  name = constructor_name (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	    {	      error ("no constructor named `%s' in visible scope",		     IDENTIFIER_POINTER (name));	      return error_mark_node;	    }	}      if (! IS_AGGR_TYPE (basetype))	{	non_aggr_error:	  if ((flags & LOOKUP_COMPLAIN) && TREE_CODE (basetype) != ERROR_MARK)	    error ("request for member `%s' in something not a structure or union", err_name);	  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;      instance = C_C_D;      instance_ptr = current_class_decl;      result = build_field_call (TYPE_BINFO (current_class_type),				 instance_ptr, name, parms, err_name);      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, TYPE_POINTER_TO (basetype), instance);    }  else if (instance == current_exception_object)    {      instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (current_exception_type),			    TREE_OPERAND (current_exception_object, 0));      mark_addressable (TREE_OPERAND (current_exception_object, 0));      result = build_field_call (TYPE_BINFO (current_exception_type),				 instance_ptr, name, parms, err_name);      if (result)	return result;      error ("exception member `%s' cannot be invoked", err_name);      return error_mark_node;    }  else    {      /* The MAIN_VARIANT of the type that `instance_ptr' winds up being.  */      tree inst_ptr_basetype;      static_call_context = (TREE_CODE (instance) == NOP_EXPR			     && TREE_OPERAND (instance, 0) == error_mark_node);      /* the base type of an instance variable is pointer to class */      basetype = TREE_TYPE (instance);      if (TREE_CODE (basetype) == REFERENCE_TYPE)	{	  basetype = TYPE_MAIN_VARIANT (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, TYPE_POINTER_TO (basetype), instance);	  inst_ptr_basetype = basetype;	}      else	{	  if (TREE_CODE (basetype) == POINTER_TYPE)

⌨️ 快捷键说明

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