typeck.c

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

C
2,225
字号
	int volatilep	  = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));	tree target;	if (tt1 == tt2)	  target = tt1;	else if (tt1 == void_type_node || tt2 == void_type_node)	  target = void_type_node;	else if (tt1 == unknown_type_node)	  target = tt2;	else if (tt2 == unknown_type_node)	  target = tt1;	else	  target = common_type (tt1, tt2);	target = cp_build_type_variant (target, constp, volatilep);	if (code1 == POINTER_TYPE)	  t1 = build_pointer_type (target);	else	  t1 = build_reference_type (target);	t1 = build_type_attribute_variant (t1, attributes);	if (TREE_CODE (target) == METHOD_TYPE)	  t1 = build_ptrmemfunc_type (t1);	return t1;      }    case ARRAY_TYPE:      {	tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));	/* Save space: see if the result is identical to one of the args.  */	if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))	  return build_type_attribute_variant (t1, attributes);	if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))	  return build_type_attribute_variant (t2, attributes);	/* Merge the element types, and have a size if either arg has one.  */	t1 = build_cplus_array_type	  (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));	return build_type_attribute_variant (t1, attributes);      }    case FUNCTION_TYPE:      /* Function types: prefer the one that specified arg types.	 If both do, merge the arg types.  Also merge the return types.  */      {	tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2));	tree p1 = TYPE_ARG_TYPES (t1);	tree p2 = TYPE_ARG_TYPES (t2);	tree rval, raises;	/* Save space: see if the result is identical to one of the args.  */	if (valtype == TREE_TYPE (t1) && ! p2)	  return build_type_attribute_variant (t1, attributes);	if (valtype == TREE_TYPE (t2) && ! p1)	  return build_type_attribute_variant (t2, attributes);	/* Simple way if one arg fails to specify argument types.  */	if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)	  {	    rval = build_function_type (valtype, p2);	    if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))	      rval = build_exception_variant (rval, raises);	    return build_type_attribute_variant (rval, attributes);	  }	raises = TYPE_RAISES_EXCEPTIONS (t1);	if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)	  {	    rval = build_function_type (valtype, p1);	    if (raises)	      rval = build_exception_variant (rval, raises);	    return build_type_attribute_variant (rval, attributes);	  }	rval = build_function_type (valtype, commonparms (p1, p2));	rval = build_exception_variant (rval, raises);	return build_type_attribute_variant (rval, attributes);      }    case RECORD_TYPE:    case UNION_TYPE:      my_friendly_assert (TYPE_MAIN_VARIANT (t1) == t1			  && TYPE_MAIN_VARIANT (t2) == t2, 306);      if (DERIVED_FROM_P (t1, t2) && binfo_or_else (t1, t2))	return build_type_attribute_variant (t1, attributes);      else if (binfo_or_else (t2, t1))	return build_type_attribute_variant (t2, attributes);      else	compiler_error ("common_type called with uncommon aggregate types");    case METHOD_TYPE:      if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))	{	  /* Get this value the long way, since TYPE_METHOD_BASETYPE	     is just the main variant of this.  */	  tree basetype;	  tree raises, t3;	  tree b1 = TYPE_OFFSET_BASETYPE (t1);	  tree b2 = TYPE_OFFSET_BASETYPE (t2);	  if (comptypes (b1, b2, 1)	      || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))	    basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));	  else	    {	      if (binfo_or_else (b2, b1) == NULL_TREE)		compiler_error ("common_type called with uncommon method types");	      basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t1)));	    }	  raises = TYPE_RAISES_EXCEPTIONS (t1);	  /* If this was a member function type, get back to the	     original type of type member function (i.e., without	     the class instance variable up front.  */	  t1 = build_function_type (TREE_TYPE (t1), TREE_CHAIN (TYPE_ARG_TYPES (t1)));	  t2 = build_function_type (TREE_TYPE (t2), TREE_CHAIN (TYPE_ARG_TYPES (t2)));	  t3 = common_type (t1, t2);	  t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3));	  t1 = build_exception_variant (t3, raises);	}      else        compiler_error ("common_type called with uncommon method types");      return build_type_attribute_variant (t1, attributes);    case OFFSET_TYPE:      if (TREE_TYPE (t1) == TREE_TYPE (t2))	{	  tree b1 = TYPE_OFFSET_BASETYPE (t1);	  tree b2 = TYPE_OFFSET_BASETYPE (t2);	  if (comptypes (b1, b2, 1)	      || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))	    return build_type_attribute_variant (t2, attributes);	  else if (binfo_or_else (b2, b1))	    return build_type_attribute_variant (t1, attributes);	}      compiler_error ("common_type called with uncommon member types");    default:      return build_type_attribute_variant (t1, attributes);    }}/* Return 1 if TYPE1 and TYPE2 raise the same exceptions.  */intcompexcepttypes (t1, t2)     tree t1, t2;{  return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);}static intcomp_array_types (cmp, t1, t2, strict)     register int (*cmp) PROTO((tree, tree, int));     tree t1, t2;     int strict;{  tree d1 = TYPE_DOMAIN (t1);  tree d2 = TYPE_DOMAIN (t2);  /* Target types must match incl. qualifiers.  */  if (!(TREE_TYPE (t1) == TREE_TYPE (t2)	|| (*cmp) (TREE_TYPE (t1), TREE_TYPE (t2), strict)))    return 0;  /* Sizes must match unless one is missing or variable.  */  if (d1 == 0 || d2 == 0 || d1 == d2      || TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST      || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST      || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST      || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)    return 1;  return ((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1))	   == TREE_INT_CST_LOW (TYPE_MIN_VALUE (d2)))	  && (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d1))	      == TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d2)))	  && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (d1))	      == TREE_INT_CST_LOW (TYPE_MAX_VALUE (d2)))	  && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d1))	      == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2))));}/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment   or various other operations.  This is what ANSI C++ speaks of as   "being the same".   For C++: argument STRICT says we should be strict about this   comparison:	2 : strict, except that if one type is a reference and	    the other is not, compare the target type of the	    reference to the type that's not a reference (ARM, p308).	    This is used for checking for invalid overloading.	1 : strict (compared according to ANSI C)	    This is used for checking whether two function decls match.	0 : <= (compared according to C++)	-1: <= or >= (relaxed)   Otherwise, pointers involving base classes and derived classes   can be mixed as valid: i.e. a pointer to a base class may be assigned   to a pointer to one of its derived classes, as per C++. A pointer to   a derived class may be passed as a parameter to a function expecting a   pointer to a base classes. These allowances do not commute. In this   case, TYPE1 is assumed to be the base class, and TYPE2 is assumed to   be the derived class.  */intcomptypes (type1, type2, strict)     tree type1, type2;     int strict;{  register tree t1 = type1;  register tree t2 = type2;  int attrval, val;  /* Suppress errors caused by previously reported errors */  if (t1 == t2)    return 1;  /* This should never happen.  */  my_friendly_assert (t1 != error_mark_node, 307);  if (t2 == error_mark_node)    return 0;  if (strict < 0)    {      /* Treat an enum type as the unsigned integer type of the same width.  */      if (TREE_CODE (t1) == ENUMERAL_TYPE)	t1 = type_for_size (TYPE_PRECISION (t1), 1);      if (TREE_CODE (t2) == ENUMERAL_TYPE)	t2 = type_for_size (TYPE_PRECISION (t2), 1);      if (t1 == t2)	return 1;    }  if (TYPE_PTRMEMFUNC_P (t1))    t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);  if (TYPE_PTRMEMFUNC_P (t2))    t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);  /* Different classes of types can't be compatible.  */  if (TREE_CODE (t1) != TREE_CODE (t2))    {      if (strict == 2	  && ((TREE_CODE (t1) == REFERENCE_TYPE)	      ^ (TREE_CODE (t2) == REFERENCE_TYPE)))	{	  if (TREE_CODE (t1) == REFERENCE_TYPE)	    return comptypes (TREE_TYPE (t1), t2, 1);	  return comptypes (t1, TREE_TYPE (t2), 1);	}      return 0;    }  if (strict > 1)    strict = 1;  /* Qualifiers must match.  */  if (TYPE_READONLY (t1) != TYPE_READONLY (t2))    return 0;  if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))    return 0;  /* Allow for two different type nodes which have essentially the same     definition.  Note that we already checked for equality of the type     type qualifiers (just above).  */  if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))    return 1;  /* ??? COMP_TYPE_ATTRIBUTES is currently useless for variables as each     attribute is its own main variant (`val' will remain 0).  */#ifndef COMP_TYPE_ATTRIBUTES#define COMP_TYPE_ATTRIBUTES(t1,t2)	1#endif  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */  if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))     return 0;  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */  val = 0;  switch (TREE_CODE (t1))    {    case RECORD_TYPE:    case UNION_TYPE:      if (CLASSTYPE_TEMPLATE_INFO (t1) && CLASSTYPE_TEMPLATE_INFO (t2)	  && CLASSTYPE_TI_TEMPLATE (t1) == CLASSTYPE_TI_TEMPLATE (t2))	{	  int i = TREE_VEC_LENGTH (CLASSTYPE_TI_ARGS (t1));	  tree *p1 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t1), 0);	  tree *p2 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t2), 0);		  while (i--)	    {	      if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')		{		  if (! comptypes (p1[i], p2[i], 1))		    return 0;		}	      else		{		  if (simple_cst_equal (p1[i], p2[i]) <= 0)		    return 0;		}	    }	  return 1;	}      if (strict <= 0)	goto look_hard;      return 0;    case OFFSET_TYPE:      val = (comptypes (build_pointer_type (TYPE_OFFSET_BASETYPE (t1)),			build_pointer_type (TYPE_OFFSET_BASETYPE (t2)), strict)	     && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict));      break;    case METHOD_TYPE:      if (! compexcepttypes (t1, t2))	return 0;      /* This case is anti-symmetrical!	 One can pass a base member (or member function)	 to something expecting a derived member (or member function),	 but not vice-versa!  */      val = (comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)	     && compparms (TYPE_ARG_TYPES (t1),			   TYPE_ARG_TYPES (t2), strict));      break;    case POINTER_TYPE:    case REFERENCE_TYPE:      t1 = TREE_TYPE (t1);      t2 = TREE_TYPE (t2);      if (t1 == t2)	{	  val = 1;	  break;	}      if (strict <= 0)	{	  if (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE)	    {	      int rval;	    look_hard:	      rval = t1 == t2 || DERIVED_FROM_P (t1, t2);	      if (rval)		{		  val = 1;		  break;		}	      if (strict < 0)		{		  val = DERIVED_FROM_P (t2, t1);		  break;		}	    }	  return 0;	}      else	val = comptypes (t1, t2, strict);      break;    case FUNCTION_TYPE:      if (! compexcepttypes (t1, t2))	return 0;      val = ((TREE_TYPE (t1) == TREE_TYPE (t2)	      || comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))	     && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2), strict));      break;    case ARRAY_TYPE:      /* Target types must match incl. qualifiers.  */      val = comp_array_types (comptypes, t1, t2, strict);      break;    case TEMPLATE_TYPE_PARM:      return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2)	&& TEMPLATE_TYPE_LEVEL (t1) == TEMPLATE_TYPE_LEVEL (t2);    case TYPENAME_TYPE:      if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))	return 0;      return comptypes (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2), 1);    }  return attrval == 2 && val == 1 ? 2 : val;}/* Return 1 if TTL and TTR are pointers to types that are equivalent,   ignoring their qualifiers.   NPTRS is the number of pointers we can strip off and keep cool.   This is used to permit (for aggr A, aggr B) A, B* to convert to A*,   but to not permit B** to convert to A**.  */intcomp_target_types (ttl, ttr, nptrs)     tree ttl, ttr;     int nptrs;{  ttl = TYPE_MAIN_VARIANT (ttl);  ttr = TYPE_MAIN_VARIANT (ttr);  if (ttl == ttr)    return 1;  if (TREE_CODE (ttr) != TREE_CODE (ttl))    return 0;  if (TREE_CODE (ttr) == POINTER_TYPE)    {      ttl = TREE_TYPE (ttl);      ttr = TREE_TYPE (ttr);      if (nptrs > 0)	{	  if (TREE_CODE (ttl) == UNKNOWN_TYPE	      || TREE_CODE (ttr) == UNKNOWN_TYPE)	    return 1;	  else if (TREE_CODE (ttl) == VOID_TYPE		   && TREE_CODE (ttr) != FUNCTION_TYPE		   && TREE_CODE (ttr) != METHOD_TYPE		   && TREE_CODE (ttr) != OFFSET_TYPE)	    return 1;	  else if (TREE_CODE (ttr) == VOID_TYPE		   && TREE_CODE (ttl) != FUNCTION_TYPE		   && TREE_CODE (ttl) != METHOD_TYPE		   && TREE_CODE (ttl) != OFFSET_TYPE)	    return -1;

⌨️ 快捷键说明

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