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

📄 method.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 4 页
字号:
	  && ! IDENTIFIER_LOCAL_VALUE (name));}#endif/* Given a tree_code CODE, and some arguments (at least one),   attempt to use an overloaded operator on the arguments.   For unary operators, only the first argument need be checked.   For binary operators, both arguments may need to be checked.   Member functions can convert class references to class pointers,   for one-level deep indirection.  More than that is not supported.   Operators [](), ()(), and ->() must be member functions.   We call function call building calls with LOOKUP_COMPLAIN if they   are our only hope.  This is true when we see a vanilla operator   applied to something of aggregate type.  If this fails, we are free   to return `error_mark_node', because we will have reported the   error.   Operators NEW and DELETE overload in funny ways: operator new takes   a single `size' parameter, and operator delete takes a pointer to the   storage being deleted.  When overloading these operators, success is   assumed.  If there is a failure, report an error message and return   `error_mark_node'.  *//* NOSTRICT */treebuild_opfncall (code, flags, xarg1, xarg2, arg3)     enum tree_code code;     int flags;     tree xarg1, xarg2, arg3;{  tree rval = 0;  tree arg1, arg2;  tree type1, type2, fnname;  tree fields1 = 0, parms = 0;  tree global_fn;  int try_second;  int binary_is_unary;  if (xarg1 == error_mark_node)    return error_mark_node;  if (code == COND_EXPR)    {      if (TREE_CODE (xarg2) == ERROR_MARK	  || TREE_CODE (arg3) == ERROR_MARK)	return error_mark_node;    }  if (code == COMPONENT_REF)    if (TREE_CODE (TREE_TYPE (xarg1)) == POINTER_TYPE)      return rval;  /* First, see if we can work with the first argument */  type1 = TREE_TYPE (xarg1);  /* Some tree codes have length > 1, but we really only want to     overload them if their first argument has a user defined type.  */  switch (code)    {    case PREINCREMENT_EXPR:    case PREDECREMENT_EXPR:    case POSTINCREMENT_EXPR:    case POSTDECREMENT_EXPR:    case COMPONENT_REF:      binary_is_unary = 1;      try_second = 0;      break;      /* ARRAY_REFs and CALL_EXPRs must overload successfully.	 If they do not, return error_mark_node instead of NULL_TREE.  */    case ARRAY_REF:      if (xarg2 == error_mark_node)	return error_mark_node;    case CALL_EXPR:      rval = error_mark_node;      binary_is_unary = 0;      try_second = 0;      break;    case VEC_NEW_EXPR:    case NEW_EXPR:      {	tree args = tree_cons (NULL_TREE, xarg2, arg3);	fnname = ansi_opname[(int) code];	if (flags & LOOKUP_GLOBAL)	  return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN,				      (struct candidate *)0);	rval = build_method_call	  (build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node),			       "new"),	   fnname, args, NULL_TREE, flags);	if (rval == error_mark_node)	  /* User might declare fancy operator new, but invoke it	     like standard one.  */	  return rval;	TREE_TYPE (rval) = xarg1;	TREE_CALLS_NEW (rval) = 1;	return rval;      }      break;    case VEC_DELETE_EXPR:    case DELETE_EXPR:      {	fnname = ansi_opname[(int) code];	if (flags & LOOKUP_GLOBAL)	  return build_overload_call (fnname,				      build_tree_list (NULL_TREE, xarg1),				      flags & LOOKUP_COMPLAIN,				      (struct candidate *)0);	rval = build_method_call	  (build_indirect_ref (build1 (NOP_EXPR, TREE_TYPE (xarg1),				       error_mark_node),			       NULL_PTR),	   fnname, tree_cons (NULL_TREE, xarg1,			       build_tree_list (NULL_TREE, xarg2)),	   NULL_TREE, flags);#if 0	/* This can happen when operator delete is protected.  */	my_friendly_assert (rval != error_mark_node, 250);	TREE_TYPE (rval) = void_type_node;#endif	return rval;      }      break;    default:      binary_is_unary = 0;      try_second = tree_code_length [(int) code] == 2;      if (try_second && xarg2 == error_mark_node)	return error_mark_node;      break;    }  if (try_second && xarg2 == error_mark_node)    return error_mark_node;  /* What ever it was, we do not know how to deal with it.  */  if (type1 == NULL_TREE)    return rval;  if (TREE_CODE (type1) == OFFSET_TYPE)    type1 = TREE_TYPE (type1);  if (TREE_CODE (type1) == REFERENCE_TYPE)    {      arg1 = convert_from_reference (xarg1);      type1 = TREE_TYPE (arg1);    }  else    {      arg1 = xarg1;    }  if (!IS_AGGR_TYPE (type1) || TYPE_PTRMEMFUNC_P (type1))    {      /* Try to fail. First, fail if unary */      if (! try_second)	return rval;      /* Second, see if second argument is non-aggregate. */      type2 = TREE_TYPE (xarg2);      if (TREE_CODE (type2) == OFFSET_TYPE)	type2 = TREE_TYPE (type2);      if (TREE_CODE (type2) == REFERENCE_TYPE)	{	  arg2 = convert_from_reference (xarg2);	  type2 = TREE_TYPE (arg2);	}      else	{	  arg2 = xarg2;	}      if (!IS_AGGR_TYPE (type2))	return rval;      try_second = 0;    }  if (try_second)    {      /* First arg may succeed; see whether second should.  */      type2 = TREE_TYPE (xarg2);      if (TREE_CODE (type2) == OFFSET_TYPE)	type2 = TREE_TYPE (type2);      if (TREE_CODE (type2) == REFERENCE_TYPE)	{	  arg2 = convert_from_reference (xarg2);	  type2 = TREE_TYPE (arg2);	}      else	{	  arg2 = xarg2;	}      if (! IS_AGGR_TYPE (type2))	try_second = 0;    }  if (type1 == unknown_type_node      || (try_second && TREE_TYPE (xarg2) == unknown_type_node))    {      /* This will not be implemented in the foreseeable future.  */      return rval;    }  if (code == MODIFY_EXPR)    fnname = ansi_assopname[(int) TREE_CODE (arg3)];  else    fnname = ansi_opname[(int) code];  global_fn = lookup_name_nonclass (fnname);  /* This is the last point where we will accept failure.  This     may be too eager if we wish an overloaded operator not to match,     but would rather a normal operator be called on a type-converted     argument.  */  if (IS_AGGR_TYPE (type1))    {      fields1 = lookup_fnfields (TYPE_BINFO (type1), fnname, 0);      /* ARM $13.4.7, prefix/postfix ++/--.  */      if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)	{	  xarg2 = integer_zero_node;	  binary_is_unary = 0;	  if (fields1)	    {	      tree t, t2;	      int have_postfix = 0;	      /* Look for an `operator++ (int)'.  If they didn't have		 one, then we fall back to the old way of doing things.  */	      for (t = TREE_VALUE (fields1); t ; t = DECL_CHAIN (t))		{		  t2 = TYPE_ARG_TYPES (TREE_TYPE (t));		  if (TREE_CHAIN (t2) != NULL_TREE		      && TREE_VALUE (TREE_CHAIN (t2)) == integer_type_node)		    {		      have_postfix = 1;		      break;		    }		}	      if (! have_postfix)		{		  char *op = POSTINCREMENT_EXPR ? "++" : "--";		  /* There's probably a LOT of code in the world that		     relies upon this old behavior.  */		  if (! flag_traditional)		    pedwarn ("no `operator%s (int)' declared for postfix `%s', using prefix operator instead",			     op, op);		  xarg2 = NULL_TREE;		  binary_is_unary = 1;		}	    }	}    }  if (fields1 == NULL_TREE && global_fn == NULL_TREE)    return rval;  /* If RVAL winds up being `error_mark_node', we will return     that... There is no way that normal semantics of these     operators will succeed.  */  /* This argument may be an uncommitted OFFSET_REF.  This is     the case for example when dealing with static class members     which are referenced from their class name rather than     from a class instance.  */  if (TREE_CODE (xarg1) == OFFSET_REF      && TREE_CODE (TREE_OPERAND (xarg1, 1)) == VAR_DECL)    xarg1 = TREE_OPERAND (xarg1, 1);  if (try_second && xarg2 && TREE_CODE (xarg2) == OFFSET_REF      && TREE_CODE (TREE_OPERAND (xarg2, 1)) == VAR_DECL)    xarg2 = TREE_OPERAND (xarg2, 1);  if (global_fn)    flags |= LOOKUP_GLOBAL;  if (code == CALL_EXPR)    {      /* This can only be a member function.  */      return build_method_call (xarg1, fnname, xarg2,				NULL_TREE, LOOKUP_NORMAL);    }  else if (tree_code_length[(int) code] == 1 || binary_is_unary)    {      parms = NULL_TREE;      rval = build_method_call (xarg1, fnname, NULL_TREE, NULL_TREE, flags);    }  else if (code == COND_EXPR)    {      parms = tree_cons (0, xarg2, build_tree_list (NULL_TREE, arg3));      rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);    }  else if (code == METHOD_CALL_EXPR)    {      /* must be a member function.  */      parms = tree_cons (NULL_TREE, xarg2, arg3);      return build_method_call (xarg1, fnname, parms, NULL_TREE,				LOOKUP_NORMAL);    }  else if (fields1)    {      parms = build_tree_list (NULL_TREE, xarg2);      rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);    }  else    {      parms = tree_cons (NULL_TREE, xarg1,			 build_tree_list (NULL_TREE, xarg2));      rval = build_overload_call (fnname, parms, flags,				  (struct candidate *)0);    }  return rval;}/* This function takes an identifier, ID, and attempts to figure out what   it means. There are a number of possible scenarios, presented in increasing   order of hair:   1) not in a class's scope   2) in class's scope, member name of the class's method   3) in class's scope, but not a member name of the class   4) in class's scope, member name of a class's variable   NAME is $1 from the bison rule. It is an IDENTIFIER_NODE.   VALUE is $$ from the bison rule. It is the value returned by lookup_name ($1)   yychar is the pending input character (suitably encoded :-).   As a last ditch, try to look up the name as a label and return that   address.   Values which are declared as being of REFERENCE_TYPE are   automatically dereferenced here (as a hack to make the   compiler faster).  */treehack_identifier (value, name, yychar)     tree value, name;     int yychar;{  tree type;  if (TREE_CODE (value) == ERROR_MARK)    {      if (current_class_name)	{	  tree fields = lookup_fnfields (TYPE_BINFO (current_class_type), name, 1);	  if (fields == error_mark_node)	    return error_mark_node;	  if (fields)	    {	      tree fndecl;	      fndecl = TREE_VALUE (fields);	      my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251);	      if (DECL_CHAIN (fndecl) == NULL_TREE)		{		  warning ("methods cannot be converted to function pointers");		  return fndecl;		}	      else		{		  error ("ambiguous request for method pointer `%s'",			 IDENTIFIER_POINTER (name));		  return error_mark_node;		}	    }	}      if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name))	{	  return IDENTIFIER_LABEL_VALUE (name);	}      return error_mark_node;    }  type = TREE_TYPE (value);  if (TREE_CODE (value) == FIELD_DECL)    {      if (current_class_decl == NULL_TREE)	{	  error ("request for member `%s' in static member function",		 IDENTIFIER_POINTER (DECL_NAME (value)));	  return error_mark_node;	}      TREE_USED (current_class_decl) = 1;      /* Mark so that if we are in a constructor, and then find that	 this field was initialized by a base initializer,	 we can emit an error message.  */      TREE_USED (value) = 1;      return build_component_ref (C_C_D, name, 0, 1);    }  if (really_overloaded_fn (value))    {      tree t = get_first_fn (value);      for (; t; t = DECL_CHAIN (t))	{	  if (TREE_CODE (t) == TEMPLATE_DECL)	    continue;	  assemble_external (t);	  TREE_USED (t) = 1;	}    }  else if (TREE_CODE (value) == TREE_LIST)    {      tree t = value;      while (t && TREE_CODE (t) == TREE_LIST)	{	  assemble_external (TREE_VALUE (t));	  TREE_USED (t) = 1;	  t = TREE_CHAIN (t);	}    }  else    {      assemble_external (value);      TREE_USED (value) = 1;    }  if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))    {      if (DECL_LANG_SPECIFIC (value)	  && DECL_CLASS_CONTEXT (value) != current_class_type)	{	  tree path;	  enum access_type access;	  register tree context	    = (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value))	      ? DECL_CLASS_CONTEXT (value)	      : DECL_CONTEXT (value);	  get_base_distance (context, current_class_type, 0, &path);	  if (path)	    {	      access = compute_access (path, value);	      if (access != access_public)		{		  if (TREE_CODE (value) == VAR_DECL)		    error ("static member `%s' is %s",			   IDENTIFIER_POINTER (name),			   TREE_PRIVATE (value) ? "private" :			   "from a private base class");		  else		    error ("enum `%s' is from private base class",			   IDENTIFIER_POINTER (name));		  return error_mark_node;		}	    }	}      return value;    }  if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value))    {      if (type == 0)	{	  error ("request for member `%s' is ambiguous in multiple inheritance lattice",		 IDENTIFIER_POINTER (name));	  return error_mark_node;	}      return value;    }  if (TREE_CODE (type) == REFERENCE_TYPE)    {      my_friendly_assert (TREE_CODE (value) == VAR_DECL			  || TREE_CODE (value) == PARM_DECL			  || TREE_CODE (value) == RESULT_DECL, 252);      return convert_from_reference (value);    }  return value;}#if 0/* Given an object OF, and a type conversion operator COMPONENT   build a call to the conversion operator, if a call is requested,   or return the address (as a pointer to member function) if one is not.   OF can be a TYPE_DECL or any kind of datum that would normally   be passed to `build_component_ref'.  It may also be NULL_TREE,   in which case `current_class_type' and `current_class_decl'   provide default values.   BASETYPE_PATH, if non-null, is the path of basetypes   to go through before we get the the instance of interest.   PROTECT says whether we apply C++ scoping rules or not.  */treebuild_component_type_expr (of, component, basetype_path, protect)     tree of, component, basetype_path;     int protect;{  tree cname = NULL_TREE;  tree tmp, last;  tree name;  int flags = protect ? LOOKUP_NORMAL : LOOKUP_COMPLAIN;  if (of)    my_friendly_assert (IS_AGGR_TYPE (TREE_TYPE (of)), 253);  my_friendly_assert (TREE_CODE (component) == TYPE_EXPR, 254);  tmp = TREE_OPERAND (component, 0);  last = NULL_TREE;  while (tmp)    {      switch (TREE_CODE (tmp))	{	case CALL_EXPR:	  if (last)	    TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0);	  else	    TREE_OPERAND (component, 0) = TREE_OPERAND (tmp, 0);	  last = groktypename (build_tree_list (TREE_TYPE (component),						TREE_OPERAND (component, 0)));	  name = build_typename_overload (last);	  TREE_TYPE (name) = last;	  if (TREE_OPERAND (tmp, 0)	      && TREE_OPERAND (tmp, 0) != void_list_node)	    {	      cp_error ("`operator %T' requires empty parameter list", last);	      TREE_OPERAND (tmp, 0) = NULL_TREE;	    }	  if (of && TREE_CODE (of) != TYPE_DECL)	    return build_method_call (of, name, NULL_TREE, NULL_TREE, flags);	  else if (of)	    {	      tree this_this;	      if (current_class_decl == NULL_TREE)		{		  cp_error ("object required for `operator %T' call",			    TREE_TYPE (name));		  return error_mark_node;		}	      this_this = convert_pointer_to (TREE_TYPE (of),					      current_class_decl);	      this_this = build_indirect_ref (this_this, NULL_PTR);	      return build_method_call (this_this, name, NULL_TREE,					NULL_TREE, flags | LOOKUP_NONVIRTUAL);	    }	  else if (current_class_decl)	    return build_method_call (tmp, name, NULL_TREE, NULL_TREE, flags);	  cp_error ("object required for `operator %T' call",		    TREE_TYPE (name));	  return error_mark_node;	case INDIRECT_REF:	case ADDR_EXPR:	case ARRAY_REF:	  break;	case SCOPE_REF:	  my_friendly_assert (cname == 0, 255);

⌨️ 快捷键说明

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