typeck.c

来自「GCC编译器源代码」· C语言 代码 · 共 2,225 行 · 第 1/5 页

C
2,225
字号
	  else if (TREE_CODE (ttl) == POINTER_TYPE		   || TREE_CODE (ttl) == ARRAY_TYPE)	    {	      if (comp_ptr_ttypes (ttl, ttr))		return 1;	      else if (comp_ptr_ttypes (ttr, ttl))		return -1;	      return 0;	    }	}      /* Const and volatile mean something different for function types,	 so the usual checks are not appropriate.  */      if (TREE_CODE (ttl) == FUNCTION_TYPE || TREE_CODE (ttl) == METHOD_TYPE)	return comp_target_types (ttl, ttr, nptrs - 1);      /* Make sure that the cv-quals change only in the same direction as	 the target type.  */      {	int t;	int c = TYPE_READONLY (ttl) - TYPE_READONLY (ttr);	int v = TYPE_VOLATILE (ttl) - TYPE_VOLATILE (ttr);	if ((c > 0 && v < 0) || (c < 0 && v > 0))	  return 0;	if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr))	  return (c + v < 0) ? -1 : 1;	t = comp_target_types (ttl, ttr, nptrs - 1);	if ((t == 1 && c + v >= 0) || (t == -1 && c + v <= 0))	  return t;	return 0;      }    }  if (TREE_CODE (ttr) == REFERENCE_TYPE)    return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);  if (TREE_CODE (ttr) == ARRAY_TYPE)    return comp_array_types (comp_target_types, ttl, ttr, 0);  else if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE)    if (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))      switch (comp_target_parms (TYPE_ARG_TYPES (ttl), TYPE_ARG_TYPES (ttr), 1))	{	case 0:	  return 0;	case 1:	  return 1;	case 2:	  return -1;	default:	  my_friendly_abort (112);	}    else      return 0;  /* for C++ */  else if (TREE_CODE (ttr) == OFFSET_TYPE)    {      /* Contravariance: we can assign a pointer to base member to a pointer	 to derived member.  Note difference from simple pointer case, where	 we can pass a pointer to derived to a pointer to base.  */      if (comptypes (TYPE_OFFSET_BASETYPE (ttr), TYPE_OFFSET_BASETYPE (ttl), 0))	return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);      else if (comptypes (TYPE_OFFSET_BASETYPE (ttl), TYPE_OFFSET_BASETYPE (ttr), 0)	       && comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))	return -1;    }  else if (IS_AGGR_TYPE (ttl))    {      if (nptrs < 0)	return 0;      if (comptypes (build_pointer_type (ttl), build_pointer_type (ttr), 0))	return 1;      if (comptypes (build_pointer_type (ttr), build_pointer_type (ttl), 0))	return -1;      return 0;    }  return 0;}/* If two types share a common base type, return that basetype.   If there is not a unique most-derived base type, this function   returns ERROR_MARK_NODE.  */static treecommon_base_type (tt1, tt2)     tree tt1, tt2;{  tree best = NULL_TREE;  int i;  /* If one is a baseclass of another, that's good enough.  */  if (UNIQUELY_DERIVED_FROM_P (tt1, tt2))    return tt1;  if (UNIQUELY_DERIVED_FROM_P (tt2, tt1))    return tt2;  /* Otherwise, try to find a unique baseclass of TT1     that is shared by TT2, and follow that down.  */  for (i = CLASSTYPE_N_BASECLASSES (tt1)-1; i >= 0; i--)    {      tree basetype = TYPE_BINFO_BASETYPE (tt1, i);      tree trial = common_base_type (basetype, tt2);      if (trial)	{	  if (trial == error_mark_node)	    return trial;	  if (best == NULL_TREE)	    best = trial;	  else if (best != trial)	    return error_mark_node;	}    }  /* Same for TT2.  */  for (i = CLASSTYPE_N_BASECLASSES (tt2)-1; i >= 0; i--)    {      tree basetype = TYPE_BINFO_BASETYPE (tt2, i);      tree trial = common_base_type (tt1, basetype);      if (trial)	{	  if (trial == error_mark_node)	    return trial;	  if (best == NULL_TREE)	    best = trial;	  else if (best != trial)	    return error_mark_node;	}    }  return best;}/* Subroutines of `comptypes'.  *//* Return 1 if two parameter type lists PARMS1 and PARMS2   are equivalent in the sense that functions with those parameter types   can have equivalent types.   If either list is empty, we win.   Otherwise, the two lists must be equivalent, element by element.   C++: See comment above about TYPE1, TYPE2, STRICT.   If STRICT == 3, it means checking is strict, but do not compare   default parameter values.  */intcompparms (parms1, parms2, strict)     tree parms1, parms2;     int strict;{  register tree t1 = parms1, t2 = parms2;  /* An unspecified parmlist matches any specified parmlist     whose argument types don't need default promotions.  */  if (strict <= 0 && t1 == 0)	return self_promoting_args_p (t2);  if (strict < 0 && t2 == 0)	return self_promoting_args_p (t1);  while (1)    {      if (t1 == 0 && t2 == 0)	return 1;      /* If one parmlist is shorter than the other,	 they fail to match, unless STRICT is <= 0.  */      if (t1 == 0 || t2 == 0)	{	  if (strict > 0)	    return 0;	  if (strict < 0)	    return 1;	  if (strict == 0)	    return t1 && TREE_PURPOSE (t1);	}      if (! comptypes (TREE_VALUE (t2), TREE_VALUE (t1), strict))	{	  if (strict > 0)	    return 0;	  if (strict == 0)	    return t2 == void_list_node && TREE_PURPOSE (t1);	  return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);	}      t1 = TREE_CHAIN (t1);      t2 = TREE_CHAIN (t2);    }}/* This really wants return whether or not parameter type lists   would make their owning functions assignment compatible or not.  */static intcomp_target_parms (parms1, parms2, strict)     tree parms1, parms2;     int strict;{  register tree t1 = parms1, t2 = parms2;  int warn_contravariance = 0;  /* An unspecified parmlist matches any specified parmlist     whose argument types don't need default promotions.     @@@ see 13.3.3 for a counterexample...  */  if (t1 == 0 && t2 != 0)    {      cp_pedwarn ("ANSI C++ prohibits conversion from `(%#T)' to `(...)'",		  parms2);      return self_promoting_args_p (t2);    }  if (t2 == 0)    return self_promoting_args_p (t1);  for (; t1 || t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))    {      tree p1, p2;      /* If one parmlist is shorter than the other,	 they fail to match, unless STRICT is <= 0.  */      if (t1 == 0 || t2 == 0)	{	  if (strict > 0)	    return 0;	  if (strict < 0)	    return 1 + warn_contravariance;	  return ((t1 && TREE_PURPOSE (t1)) + warn_contravariance);	}      p1 = TREE_VALUE (t1);      p2 = TREE_VALUE (t2);      if (p1 == p2)	continue;      if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE)	  || (TREE_CODE (p1) == REFERENCE_TYPE && TREE_CODE (p2) == REFERENCE_TYPE))	{	  if (strict <= 0	      && (TYPE_MAIN_VARIANT (TREE_TYPE (p1))		  == TYPE_MAIN_VARIANT (TREE_TYPE (p2))))	    continue;	  /* The following is wrong for contravariance,	     but many programs depend on it.  */	  if (TREE_TYPE (p1) == void_type_node)	    continue;	  if (TREE_TYPE (p2) == void_type_node)	    {	      warn_contravariance = 1;	      continue;	    }	  if (IS_AGGR_TYPE (TREE_TYPE (p1)))	    {	      if (comptypes (p2, p1, 0) == 0)		{		  if (comptypes (p1, p2, 0) != 0)		    warn_contravariance = 1;		  else		    return 0;		}	      continue;	    }	}      /* Note backwards order due to contravariance.  */      if (comp_target_types (p2, p1, 1) == 0)	{	  if (comp_target_types (p1, p2, 1))	    {	      warn_contravariance = 1;	      continue;	    }	  if (strict != 0)	    return 0;	}      /* Target types are compatible--just make sure that if	 we use parameter lists, that they are ok as well.  */      if (TREE_CODE (p1) == FUNCTION_TYPE || TREE_CODE (p1) == METHOD_TYPE)	switch (comp_target_parms (TYPE_ARG_TYPES (p1),				   TYPE_ARG_TYPES (p2),				   strict))	  {	  case 0:	    return 0;	  case 1:	    break;	  case 2:	    warn_contravariance = 1;	  }      if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))	{	  int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));	  if (cmp < 0)	    my_friendly_abort (114);	  if (cmp == 0)	    return 0;	}    }  return 1 + warn_contravariance;}/* Return 1 if PARMS specifies a fixed number of parameters   and none of their types is affected by default promotions.  */intself_promoting_args_p (parms)     tree parms;{  register tree t;  for (t = parms; t; t = TREE_CHAIN (t))    {      register tree type = TREE_VALUE (t);      if (TREE_CHAIN (t) == 0 && type != void_type_node)	return 0;      if (type == 0)	return 0;      if (TYPE_MAIN_VARIANT (type) == float_type_node)	return 0;      if (C_PROMOTING_INTEGER_TYPE_P (type))	return 0;    }  return 1;}/* Return an unsigned type the same as TYPE in other respects.   C++: must make these work for type variants as well.  */treeunsigned_type (type)     tree type;{  tree type1 = TYPE_MAIN_VARIANT (type);  if (type1 == signed_char_type_node || type1 == char_type_node)    return unsigned_char_type_node;  if (type1 == integer_type_node)    return unsigned_type_node;  if (type1 == short_integer_type_node)    return short_unsigned_type_node;  if (type1 == long_integer_type_node)    return long_unsigned_type_node;  if (type1 == long_long_integer_type_node)    return long_long_unsigned_type_node;  if (type1 == intDI_type_node)    return unsigned_intDI_type_node;  if (type1 == intSI_type_node)    return unsigned_intSI_type_node;  if (type1 == intHI_type_node)    return unsigned_intHI_type_node;  if (type1 == intQI_type_node)    return unsigned_intQI_type_node;  return signed_or_unsigned_type (1, type);}/* Return a signed type the same as TYPE in other respects.  */treesigned_type (type)     tree type;{  tree type1 = TYPE_MAIN_VARIANT (type);  if (type1 == unsigned_char_type_node || type1 == char_type_node)    return signed_char_type_node;  if (type1 == unsigned_type_node)    return integer_type_node;  if (type1 == short_unsigned_type_node)    return short_integer_type_node;  if (type1 == long_unsigned_type_node)    return long_integer_type_node;  if (type1 == long_long_unsigned_type_node)    return long_long_integer_type_node;  if (type1 == unsigned_intDI_type_node)    return intDI_type_node;  if (type1 == unsigned_intSI_type_node)    return intSI_type_node;  if (type1 == unsigned_intHI_type_node)    return intHI_type_node;  if (type1 == unsigned_intQI_type_node)    return intQI_type_node;  return signed_or_unsigned_type (0, type);}/* Return a type the same as TYPE except unsigned or   signed according to UNSIGNEDP.  */treesigned_or_unsigned_type (unsignedp, type)     int unsignedp;     tree type;{  if (! INTEGRAL_TYPE_P (type)      || TREE_UNSIGNED (type) == unsignedp)    return type;  if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))    return unsignedp ? unsigned_char_type_node : signed_char_type_node;  if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))     return unsignedp ? unsigned_type_node : integer_type_node;  if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))     return unsignedp ? short_unsigned_type_node : short_integer_type_node;  if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))     return unsignedp ? long_unsigned_type_node : long_integer_type_node;  if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))     return (unsignedp ? long_long_unsigned_type_node	    : long_long_integer_type_node);  return type;}/* Compute the value of the `sizeof' operator.  */treec_sizeof (type)     tree type;{  enum tree_code code = TREE_CODE (type);  tree t;  if (processing_template_decl)    return build_min (SIZEOF_EXPR, sizetype, type);  if (code == FUNCTION_TYPE)    {      if (pedantic || warn_pointer_arith)	pedwarn ("ANSI C++ forbids taking the sizeof a function type");      return size_int (1);    }  if (code == METHOD_TYPE)    {      if (pedantic || warn_pointer_arith)	pedwarn ("ANSI C++ forbids taking the sizeof a method type");      return size_int (1);    }  if (code == VOID_TYPE)    {      if (pedantic || warn_pointer_arith)	pedwarn ("ANSI C++ forbids taking the sizeof a void type");      return size_int (1);    }  if (code == ERROR_MARK)

⌨️ 快捷键说明

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