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

📄 cp-method.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
      try_second = 0;      break;    case POSTDECREMENT_EXPR:      code = PREDECREMENT_EXPR;      binary_is_unary = 1;      try_second = 0;      break;    case PREDECREMENT_EXPR:    case POSTINCREMENT_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 NEW_EXPR:      {	/* For operators `new' (`delete'), only check visibility	   if we are in a constructor (destructor), and we are	   allocating for that constructor's (destructor's) type.  */	fnname = ansi_opname[(int) NEW_EXPR];	if (flags & LOOKUP_GLOBAL)	  return build_overload_call (fnname, tree_cons (NULL_TREE, xarg2, arg3),				      flags & LOOKUP_COMPLAIN, 0);	if (current_function_decl == NULL_TREE	    || !DECL_CONSTRUCTOR_P (current_function_decl)	    || current_class_type != TYPE_MAIN_VARIANT (type1))	  flags = LOOKUP_COMPLAIN;	rval = build_method_call (build1 (NOP_EXPR, xarg1, error_mark_node),				  fnname, tree_cons (NULL_TREE, xarg2, arg3),				  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 DELETE_EXPR:      {	/* See comment above.  */	fnname = ansi_opname[(int) DELETE_EXPR];	if (flags & LOOKUP_GLOBAL)	  return build_overload_call (fnname,				      tree_cons (NULL_TREE, xarg1,						 build_tree_list (NULL_TREE, xarg2)),				      flags & LOOKUP_COMPLAIN, 0);	if (current_function_decl == NULL_TREE	    || !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (current_function_decl))	    || current_class_type != TYPE_MAIN_VARIANT (type1))	  flags = LOOKUP_COMPLAIN;	rval = build_method_call (build1 (NOP_EXPR, TREE_TYPE (xarg1),					  error_mark_node),				  fnname, tree_cons (NULL_TREE, xarg1,						     build_tree_list (NULL_TREE, xarg2)),				  NULL_TREE, flags);	/* This happens when the user mis-declares `operator delete'.	   Should now be impossible.  */	my_friendly_assert (rval != error_mark_node, 250);	TREE_TYPE (rval) = void_type_node;	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))    {      /* 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 forseeable future.  */      return rval;    }  if (code == MODIFY_EXPR)    fnname = ansi_assopname[(int) TREE_CODE (arg3)];  else    fnname = ansi_opname[(int) code];  global_fn = IDENTIFIER_GLOBAL_VALUE (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);  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 & LOOKUP_COMPLAIN, 0);    }  /* If we did not win, do not lose yet, since type conversion may work.  */  if (TREE_CODE (rval) == ERROR_MARK)    {      if (flags & LOOKUP_COMPLAIN)	return rval;      return 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, 0);	  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;      if (yychar == '(')	if (! ((TYPE_LANG_SPECIFIC (type)		&& TYPE_OVERLOADS_CALL_EXPR (type))	       || (TREE_CODE (type) == REFERENCE_TYPE		   && TYPE_LANG_SPECIFIC (TREE_TYPE (type))		   && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (type))))	    && TREE_CODE (type) != FUNCTION_TYPE	    && TREE_CODE (type) != METHOD_TYPE	    && (TREE_CODE (type) != POINTER_TYPE		|| (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE		    && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE)))	  {	    error ("component `%s' is not a method",		   IDENTIFIER_POINTER (name));	    return error_mark_node;	  }      /* 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 (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_CLASS_CONTEXT (value) != current_class_type)	{	  tree path;	  enum visibility_type visibility;	  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);	  visibility = compute_visibility (path, value);	  if (visibility != visibility_public)	    {	      if (TREE_CODE (value) == VAR_DECL)		error ("static member `%s' is from private base class",		       IDENTIFIER_POINTER (name));	      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, 252);      if (DECL_REFERENCE_SLOT (value))	return DECL_REFERENCE_SLOT (value);    }  return value;}/* 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);	  if (TREE_OPERAND (tmp, 0)	      && TREE_OPERAND (tmp, 0) != void_list_node)	    {	      error ("operator <typename> requires empty parameter list");	      TREE_OPERAND (tmp, 0) = NULL_TREE;	    }	  last = groktypename (build_tree_list (TREE_TYPE (component),						TREE_OPERAND (component, 0)));	  name = build_typename_overload (last);	  TREE_TYPE (name) = last;	  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)		{		  error ("object required for `operator <typename>' call");		  return error_mark_node;		}	      this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl);	      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);	  error ("object required for `operator <typename>' call");	  return error_mark_node;	case INDIRECT_REF:	case ADDR_EXPR:	case ARRAY_REF:	  break;	case SCOPE_REF:	  my_friendly_assert (cname == 0, 255);	  cname = TREE_OPERAND (tmp, 0);	  tmp = TREE_OPERAND (tmp, 1);	  break;	default:	  my_friendly_abort (77);	}      last = tmp;      tmp = 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 (of && TREE_CODE (of) == TYPE_DECL)    {      if (cname == NULL_TREE)	{	  cname = DECL_NAME (of);	  of = NULL_TREE;	}      else my_friendly_assert (cname == DECL_NAME (of), 256);    }  if (of)    {      tree this_this;      if (current_class_decl == NULL_TREE)	{	  error ("object required for `operator <typename>' call");	  return error_mark_node;	}      this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl);      return build_component_ref (this_this, name, 0, protect);    }  else if (cname)    return build_offset_ref (cname, name);  else if (current_class_name)    return build_offset_ref (current_class_name, name);  error ("object required for `operator <typename>' member reference");  return error_mark_node;}

⌨️ 快捷键说明

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