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

📄 cp-typeck.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it     unless we are not to support things not strictly ANSI.  */  switch (TREE_CODE (datum))    {    case COMPOUND_EXPR:      {	tree value = build_component_ref (TREE_OPERAND (datum, 1), component,					  basetype_path, protect);	return build (COMPOUND_EXPR, TREE_TYPE (value),		      TREE_OPERAND (datum, 0), value);      }    case COND_EXPR:      return build_conditional_expr	(TREE_OPERAND (datum, 0),	 build_component_ref (TREE_OPERAND (datum, 1), component,			      basetype_path, protect),	 build_component_ref (TREE_OPERAND (datum, 2), component,			      basetype_path, protect));    }  if (code == REFERENCE_TYPE)    {#if 0      /* TREE_REFERENCE_EXPRs are not converted by `convert_from_reference'.	 @@ Maybe that is not right.  */      if (TREE_REFERENCE_EXPR (datum))	datum = build1 (INDIRECT_REF, TREE_TYPE (basetype), datum);      else#endif	datum = convert_from_reference (datum);      basetype = TREE_TYPE (datum);      code = TREE_CODE (basetype);    }  /* First, see if there is a field or component with name COMPONENT. */  if (TREE_CODE (component) == TREE_LIST)    {      my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE		&& DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);      return build (COMPONENT_REF, TREE_TYPE (component), datum, component);    }  if (TREE_CODE (component) == TYPE_EXPR)    return build_component_type_expr (datum, component, NULL_TREE, protect);  if (! IS_AGGR_TYPE_CODE (code))    {      if (code != ERROR_MARK)	error ("request for member `%s' in something not a class, structure or union",	       IDENTIFIER_POINTER (component));      return error_mark_node;    }  if (TYPE_SIZE (basetype) == 0)    {      incomplete_type_error (0, basetype);      return error_mark_node;    }  if (TREE_CODE (component) == BIT_NOT_EXPR)    {      if (TYPE_IDENTIFIER (basetype) != TREE_OPERAND (component, 0))	{	  error_with_aggr_type (basetype,				"destructor specifier `%s::~%s' must have matching names",				IDENTIFIER_POINTER (TREE_OPERAND (component, 0)));	  return error_mark_node;	}      if (! TYPE_HAS_DESTRUCTOR (basetype))	{	  error_with_aggr_type (basetype, "type `%s' has no destructor");	  return error_mark_node;	}      return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);    }  /* Look up component name in the structure type definition.  */  if (CLASSTYPE_VFIELD (basetype)      && DECL_NAME (CLASSTYPE_VFIELD (basetype)) == component)    /* Special-case this because if we use normal lookups in an ambiguous       hierarchy, the compiler will abort (because vptr lookups are       not supposed to be ambiguous.  */    field = CLASSTYPE_VFIELD (basetype);  else    {      if (basetype_path == NULL_TREE)	basetype_path = TYPE_BINFO (basetype);      field = lookup_field (basetype_path, component,			    protect && ! VFIELD_NAME_P (component), 0);      if (field == error_mark_node)	return error_mark_node;      if (field == NULL_TREE)	{	  /* Not found as a data field, look for it as a method.  If found,	     then if this is the only possible one, return it, else	     report ambiguity error.  */	  tree fndecls = lookup_fnfields (basetype_path, component, 1);	  if (fndecls)	    {	      if (TREE_CHAIN (fndecls) == NULL_TREE		  && DECL_CHAIN (TREE_VALUE (fndecls)) == NULL_TREE)		{		  enum visibility_type visibility;		  tree fndecl;		  /* Unique, so use this one now.  */		  basetype = TREE_PURPOSE (fndecls);		  fndecl = TREE_VALUE (fndecls);		  visibility = compute_visibility (TREE_PURPOSE (fndecls), fndecl);		  if (visibility == visibility_public)		    {		      if (DECL_VINDEX (fndecl)			  && ! resolves_to_fixed_type_p (datum, 0))			{			  tree addr = build_unary_op (ADDR_EXPR, datum, 0);			  addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr);			  datum = build_indirect_ref (addr);			  my_friendly_assert (datum != error_mark_node, 310);			  fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));			}		      return fndecl;		    }		  if (visibility == visibility_protected)		    error_with_decl (fndecl, "member function `%s' is protected");		  else		    error_with_decl (fndecl, "member function `%s' is private");		  return error_mark_node;		}	      else		return build (COMPONENT_REF, unknown_type_node, datum, fndecls);	    }	  if (component == ansi_opname[(int) TYPE_EXPR])	    error ("%s has no such type conversion operator",		   code == RECORD_TYPE ? "structure" : "union");	  else	    error (code == RECORD_TYPE		   ? "structure has no member named `%s'"		   : "union has no member named `%s'",		   IDENTIFIER_POINTER (component));	  return error_mark_node;	}      else if (TREE_TYPE (field) == error_mark_node)	return error_mark_node;      if (TREE_CODE (field) != FIELD_DECL)	{	  if (TREE_CODE (field) == TYPE_DECL)	    {	      error ("invalid use of type decl `%s' as expression",		     IDENTIFIER_POINTER (DECL_NAME (field)));	      return error_mark_node;	    } 	  if (DECL_RTL (field) != 0)	    assemble_external (field);	  TREE_USED (field) = 1;	  return field;	}    }  if (DECL_FIELD_CONTEXT (field) != basetype      && TYPE_USES_COMPLEX_INHERITANCE (basetype))    {      tree addr = build_unary_op (ADDR_EXPR, datum, 0);      if (integer_zerop (addr))	{	  error ("invalid reference to NULL ptr, use ptr-to-member instead");	  return error_mark_node;	}      addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);      datum = build_indirect_ref (addr);      my_friendly_assert (datum != error_mark_node, 311);    }  ref = build (COMPONENT_REF, TREE_TYPE (field), break_out_cleanups (datum), field);  if (TREE_READONLY (datum) || TREE_READONLY (field))    TREE_READONLY (ref) = 1;  if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))    TREE_THIS_VOLATILE (ref) = 1;  return ref;}/* Given an expression PTR for a pointer, return an expression   for the value pointed to.   ERRORSTRING is the name of the operator to appear in error messages.   This function may need to overload OPERATOR_FNNAME.   Must also handle REFERENCE_TYPEs for C++.  */treebuild_x_indirect_ref (ptr, errorstring)     tree ptr;     char *errorstring;{  tree rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr);  if (rval) return rval;  return build_indirect_ref (ptr, errorstring);}treebuild_indirect_ref (ptr, errorstring)     tree ptr;     char *errorstring;{  register tree pointer = default_conversion (ptr);  register tree type = TREE_TYPE (pointer);  if (ptr == current_class_decl)    return C_C_D;  if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)    if (TREE_CODE (pointer) == ADDR_EXPR	&& (TREE_TYPE (TREE_OPERAND (pointer, 0))	    == TREE_TYPE (type)))      return TREE_OPERAND (pointer, 0);    else      {	tree t = TREE_TYPE (type);	register tree ref = build1 (INDIRECT_REF,				    TYPE_MAIN_VARIANT (t), pointer);	TREE_READONLY (ref) = TYPE_READONLY (t);	TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);	TREE_SIDE_EFFECTS (ref)	  = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);	return ref;      }  else if (pointer != error_mark_node)    {      if (errorstring)	error ("invalid type argument of `%s'", errorstring);      else	error ("invalid type argument");    }  return error_mark_node;}/* This handles expressions of the form "a[i]", which denotes   an array reference.   This is logically equivalent in C to *(a+i), but we may do it differently.   If A is a variable or a member, we generate a primitive ARRAY_REF.   This avoids forcing the array out of registers, and can work on   arrays that are not lvalues (for example, members of structures returned   by functions).   If INDEX is of some user-defined type, it must be converted to   integer type.  Otherwise, to make a compatible PLUS_EXPR, it   will inherit the type of the array, which will be some pointer type.  */treebuild_x_array_ref (array, index)     tree array, index;{  tree rval;  rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, index);  if (rval)    return rval;  return build_array_ref (array, index);}treebuild_array_ref (array, index)     tree array, index;{  tree itype;  if (index == 0)    {      error ("subscript missing in array reference");      return error_mark_node;    }  if (TREE_TYPE (array) == error_mark_node      || TREE_TYPE (index) == error_mark_node)    return error_mark_node;  itype = TREE_TYPE (index);  if (IS_AGGR_TYPE (itype))    {      if (TYPE_HAS_INT_CONVERSION (itype))	index = build_type_conversion (CONVERT_EXPR,				       integer_type_node, index, 1);      else	{	  error_with_aggr_type (itype,				"type `%s' requires integer conversion for array indexing");	  return error_mark_node;	}    }  if (TREE_CODE (itype) == REFERENCE_TYPE)    {      index = convert_from_reference (index);      itype = TREE_TYPE (index);    }  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE      && TREE_CODE (array) != INDIRECT_REF)    {      tree rval, type;      /* Subscripting with type char is likely to lose	 on a machine where chars are signed.	 So warn on any machine, but optionally.	 Don't warn for unsigned char since that type is safe.	 Don't warn for signed char because anyone who uses that	 must have done so deliberately.  */      if (warn_char_subscripts	  && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)	warning ("array subscript has type `char'");      /* Apply default promotions *after* noticing character types.  */      index = default_conversion (index);      if (TREE_CODE (TREE_TYPE (index)) != INTEGER_TYPE)	{	  error ("array subscript is not an integer");	  return error_mark_node;	}      /* An array that is indexed by a non-constant	 cannot be stored in a register; we must be able to do	 address arithmetic on its address.	 Likewise an array of elements of variable size.  */      if (TREE_CODE (index) != INTEGER_CST	  || (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))) != 0	      && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))	{	  if (mark_addressable (array) == 0)	    return error_mark_node;	}      /* Note in C++ we don't bother warning about subscripting a	 `register' array, since it's legal in C++ to take the address	 of something with that storage specification.  */      if (pedantic && !lvalue_p (array))	pedwarn ("ANSI C++ forbids subscripting non-lvalue array");      if (pedantic)	{	  tree foo = array;	  while (TREE_CODE (foo) == COMPONENT_REF)	    foo = TREE_OPERAND (foo, 0);	  if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))	    pedwarn ("ANSI C++ forbids subscripting non-lvalue array");	}      type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));      rval = build (ARRAY_REF, type, array, index);      /* Array ref is const/volatile if the array elements are	 or if the array is..  */      TREE_READONLY (rval)	|= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))	    | TREE_READONLY (array));      TREE_SIDE_EFFECTS (rval)	|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))	    | TREE_SIDE_EFFECTS (array));      TREE_THIS_VOLATILE (rval)	|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))	    /* This was added by rms on 16 Nov 91.	       It fixes  vol struct foo *a;  a->elts[1] 	       in an inline function.	       Hope it doesn't break something else.  */	    | TREE_THIS_VOLATILE (array));      return require_complete_type (fold (rval));    }  {    tree ar = default_conversion (array);    tree ind = default_conversion (index);    /* Put the integer in IND to simplify error checking.  */    if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)      {	tree temp = ar;	ar = ind;	ind = temp;      }    if (ar == error_mark_node)      return ar;    if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE)      {	error ("subscripted value is neither array nor pointer");	return error_mark_node;      }    if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)      {	error ("array subscript is not an integer");	return error_mark_node;      }    return build_indirect_ref (build_binary_op_nodefault (PLUS_EXPR, ar, ind, PLUS_EXPR),			       "array indexing");  }}/* Build a function call to function FUNCTION with parameters PARAMS.   PARAMS is a list--a chain of TREE_LIST nodes--in which the   TREE_VALUE of each node is a parameter-expression.   FUNCTION's data type may be a function type or a pointer-to-function.   For C++: If FUNCTION's data type is a TREE_LIST, then the tree list   is the list of possible methods that FUNCTION could conceivably   be.  If the list of methods comes from a class, then it will be   a list of lists (where each element is associated with the class   that produced it), otherwise it will be a simple list (for   functions overloaded in global scope).   In the first case, TREE_VALUE (function) is the head of one of those   lists, and TREE_PURPOSE is the name of the function.   In the second case, TREE_PURPOSE (function) is the function's   name directly.   DECL is the class instance variable, usually CURRENT_CLASS_DECL.  *//* * [eichin:19911015.1726EST] actually return a possibly incomplete * type */treebuild_x_function_call (function, params, decl)     tree function, params, decl;{  extern tree build_overload_call_maybe ();  tree type = TREE_TYPE (function);  int is_method = ((TREE_CODE (function) == TREE_LIST		    && current_class_type != NULL_TREE		    && IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function)) == function)		   || TREE_CODE (function) == IDENTIFIER_NODE		   || TREE_CODE (type) == METHOD_TYPE		   || (TREE_CODE (type) == POINTER_TYPE

⌨️ 快捷键说明

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