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

📄 c-typeck.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
		    warn_for_assignment ("%s as complex rather than floating due to prototype", (char *) 0, name, parmnum + 1);		  else if (TREE_CODE (type) == REAL_TYPE			   && INTEGRAL_TYPE_P (TREE_TYPE (val)))		    warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1);		  else if (TREE_CODE (type) == REAL_TYPE			   && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)		    warn_for_assignment ("%s as floating rather than complex due to prototype", (char *) 0, name, parmnum + 1);		  /* ??? At some point, messages should be written about		     conversions between complex types, but that's too messy		     to do now.  */		  else if (TREE_CODE (type) == REAL_TYPE			   && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)		    {		      /* Warn if any argument is passed as `float',			 since without a prototype it would be `double'.  */		      if (formal_prec == TYPE_PRECISION (float_type_node))			warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1);		    }		  /* Detect integer changing in width or signedness.  */		  else if (INTEGRAL_TYPE_P (type)			   && INTEGRAL_TYPE_P (TREE_TYPE (val)))		    {		      tree would_have_been = default_conversion (val);		      tree type1 = TREE_TYPE (would_have_been);		      if (TREE_CODE (type) == ENUMERAL_TYPE			  && type == TREE_TYPE (val))			/* No warning if function asks for enum			   and the actual arg is that enum type.  */			;		      else if (formal_prec != TYPE_PRECISION (type1))			warn_for_assignment ("%s with different width due to prototype", (char *) 0, name, parmnum + 1);		      else if (TREE_UNSIGNED (type) == TREE_UNSIGNED (type1))			;		      /* Don't complain if the formal parameter type			 is an enum, because we can't tell now whether			 the value was an enum--even the same enum.  */		      else if (TREE_CODE (type) == ENUMERAL_TYPE)			;		      else if (TREE_CODE (val) == INTEGER_CST			       && int_fits_type_p (val, type))			/* Change in signedness doesn't matter			   if a constant value is unaffected.  */			;		      /* Likewise for a constant in a NOP_EXPR.  */		      else if (TREE_CODE (val) == NOP_EXPR			       && TREE_CODE (TREE_OPERAND (val, 0)) == INTEGER_CST			       && int_fits_type_p (TREE_OPERAND (val, 0), type))			;#if 0 /* We never get such tree structure here.  */		      else if (TREE_CODE (TREE_TYPE (val)) == ENUMERAL_TYPE			       && int_fits_type_p (TYPE_MIN_VALUE (TREE_TYPE (val)), type)			       && int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (val)), type))			/* Change in signedness doesn't matter			   if an enum value is unaffected.  */			;#endif		      /* If the value is extended from a narrower			 unsigned type, it doesn't matter whether we			 pass it as signed or unsigned; the value			 certainly is the same either way.  */		      else if (TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type)			       && TREE_UNSIGNED (TREE_TYPE (val)))			;		      else if (TREE_UNSIGNED (type))			warn_for_assignment ("%s as unsigned due to prototype", (char *) 0, name, parmnum + 1);		      else			warn_for_assignment ("%s as signed due to prototype", (char *) 0, name, parmnum + 1);		    }		}	      parmval = convert_for_assignment (type, val, 					        (char *)0, /* arg passing  */						fundecl, name, parmnum + 1);	      #ifdef PROMOTE_PROTOTYPES	      if ((TREE_CODE (type) == INTEGER_TYPE		   || TREE_CODE (type) == ENUMERAL_TYPE)		  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))		parmval = default_conversion (parmval);#endif	    }	  result = tree_cons (NULL_TREE, parmval, result);	}      else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE               && (TYPE_PRECISION (TREE_TYPE (val))	           < TYPE_PRECISION (double_type_node)))	/* Convert `float' to `double'.  */	result = tree_cons (NULL_TREE, convert (double_type_node, val), result);      else	/* Convert `short' and `char' to full-size `int'.  */	result = tree_cons (NULL_TREE, default_conversion (val), result);      if (typetail)	typetail = TREE_CHAIN (typetail);    }  if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)    {      if (name)	error ("too few arguments to function `%s'",	       IDENTIFIER_POINTER (name));      else	error ("too few arguments to function");    }  return nreverse (result);}/* This is the entry point used by the parser   for binary operators in the input.   In addition to constructing the expression,   we check for operands that were written with other binary operators   in a way that is likely to confuse the user.  */treeparser_build_binary_op (code, arg1, arg2)     enum tree_code code;     tree arg1, arg2;{  tree result = build_binary_op (code, arg1, arg2, 1);  char class;  char class1 = TREE_CODE_CLASS (TREE_CODE (arg1));  char class2 = TREE_CODE_CLASS (TREE_CODE (arg2));  enum tree_code code1 = ERROR_MARK;  enum tree_code code2 = ERROR_MARK;  if (class1 == 'e' || class1 == '1'      || class1 == '2' || class1 == '<')    code1 = C_EXP_ORIGINAL_CODE (arg1);  if (class2 == 'e' || class2 == '1'      || class2 == '2' || class2 == '<')    code2 = C_EXP_ORIGINAL_CODE (arg2);  /* Check for cases such as x+y<<z which users are likely     to misinterpret.  If parens are used, C_EXP_ORIGINAL_CODE     is cleared to prevent these warnings.  */  if (warn_parentheses)    {      if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)	{	  if (code1 == PLUS_EXPR || code1 == MINUS_EXPR	      || code2 == PLUS_EXPR || code2 == MINUS_EXPR)	    warning ("suggest parentheses around + or - inside shift");	}      if (code == TRUTH_ORIF_EXPR)	{	  if (code1 == TRUTH_ANDIF_EXPR	      || code2 == TRUTH_ANDIF_EXPR)	    warning ("suggest parentheses around && within ||");	}      if (code == BIT_IOR_EXPR)	{	  if (code1 == BIT_AND_EXPR || code1 == BIT_XOR_EXPR	      || code1 == PLUS_EXPR || code1 == MINUS_EXPR	      || code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR	      || code2 == PLUS_EXPR || code2 == MINUS_EXPR)	    warning ("suggest parentheses around arithmetic in operand of |");	  /* Check cases like x|y==z */	  if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')	    warning ("suggest parentheses around comparison in operand of |");	}      if (code == BIT_XOR_EXPR)	{	  if (code1 == BIT_AND_EXPR	      || code1 == PLUS_EXPR || code1 == MINUS_EXPR	      || code2 == BIT_AND_EXPR	      || code2 == PLUS_EXPR || code2 == MINUS_EXPR)	    warning ("suggest parentheses around arithmetic in operand of ^");	  /* Check cases like x^y==z */	  if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')	    warning ("suggest parentheses around comparison in operand of ^");	}      if (code == BIT_AND_EXPR)	{	  if (code1 == PLUS_EXPR || code1 == MINUS_EXPR	      || code2 == PLUS_EXPR || code2 == MINUS_EXPR)	    warning ("suggest parentheses around + or - in operand of &");	  /* Check cases like x&y==z */	  if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')	    warning ("suggest parentheses around comparison in operand of &");	}    }  /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */  if (TREE_CODE_CLASS (code) == '<' && extra_warnings      && (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<'))    warning ("comparisons like X<=Y<=Z do not have their mathematical meaning");  unsigned_conversion_warning (result, arg1);  unsigned_conversion_warning (result, arg2);  overflow_warning (result);  class = TREE_CODE_CLASS (TREE_CODE (result));  /* Record the code that was specified in the source,     for the sake of warnings about confusing nesting.  */  if (class == 'e' || class == '1'      || class == '2' || class == '<')    C_SET_EXP_ORIGINAL_CODE (result, code);  else    {      int flag = TREE_CONSTANT (result);      /* We used to use NOP_EXPR rather than NON_LVALUE_EXPR	 so that convert_for_assignment wouldn't strip it.	 That way, we got warnings for things like p = (1 - 1).	 But it turns out we should not get those warnings.  */      result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result);      C_SET_EXP_ORIGINAL_CODE (result, code);      TREE_CONSTANT (result) = flag;    }  return result;}/* Build a binary-operation expression without default conversions.   CODE is the kind of expression to build.   This function differs from `build' in several ways:   the data type of the result is computed and recorded in it,   warnings are generated if arg data types are invalid,   special handling for addition and subtraction of pointers is known,   and some optimization is done (operations on narrow ints   are done in the narrower type when that gives the same result).   Constant folding is also done before the result is returned.   Note that the operands will never have enumeral types, or function   or array types, because either they will have the default conversions   performed or they have both just been converted to some other type in which   the arithmetic is to be done.  */treebuild_binary_op (code, orig_op0, orig_op1, convert_p)     enum tree_code code;     tree orig_op0, orig_op1;     int convert_p;{  tree type0, type1;  register enum tree_code code0, code1;  tree op0, op1;  /* Expression code to give to the expression when it is built.     Normally this is CODE, which is what the caller asked for,     but in some special cases we change it.  */  register enum tree_code resultcode = code;  /* Data type in which the computation is to be performed.     In the simplest cases this is the common type of the arguments.  */  register tree result_type = NULL;  /* Nonzero means operands have already been type-converted     in whatever way is necessary.     Zero means they need to be converted to RESULT_TYPE.  */  int converted = 0;  /* Nonzero means create the expression with this type, rather than     RESULT_TYPE.  */  tree build_type = 0;  /* Nonzero means after finally constructing the expression     convert it to this type.  */  tree final_type = 0;  /* Nonzero if this is an operation like MIN or MAX which can     safely be computed in short if both args are promoted shorts.     Also implies COMMON.     -1 indicates a bitwise operation; this makes a difference     in the exact conditions for when it is safe to do the operation     in a narrower mode.  */  int shorten = 0;  /* Nonzero if this is a comparison operation;     if both args are promoted shorts, compare the original shorts.     Also implies COMMON.  */  int short_compare = 0;  /* Nonzero if this is a right-shift operation, which can be computed on the     original short and then promoted if the operand is a promoted short.  */  int short_shift = 0;  /* Nonzero means set RESULT_TYPE to the common type of the args.  */  int common = 0;  if (convert_p)    {      op0 = default_conversion (orig_op0);      op1 = default_conversion (orig_op1);    }  else    {      op0 = orig_op0;      op1 = orig_op1;    }  type0 = TREE_TYPE (op0);  type1 = TREE_TYPE (op1);  /* The expression codes of the data types of the arguments tell us     whether the arguments are integers, floating, pointers, etc.  */  code0 = TREE_CODE (type0);  code1 = TREE_CODE (type1);  /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */  STRIP_TYPE_NOPS (op0);  STRIP_TYPE_NOPS (op1);  /* If an error was already reported for one of the arguments,     avoid reporting another error.  */  if (code0 == ERROR_MARK || code1 == ERROR_MARK)    return error_mark_node;  switch (code)    {    case PLUS_EXPR:      /* Handle the pointer + int case.  */      if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)	return pointer_int_sum (PLUS_EXPR, op0, op1);      else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)	return pointer_int_sum (PLUS_EXPR, op1, op0);      else	common = 1;      break;    case MINUS_EXPR:      /* Subtraction of two similar pointers.	 We must subtract them as integers, then divide by object size.  */      if (code0 == POINTER_TYPE && code1 == POINTER_TYPE	  && comp_target_types (type0, type1))	return pointer_diff (op0, op1);      /* Handle pointer minus int.  Just like pointer plus int.  */      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)	return pointer_int_sum (MINUS_EXPR, op0, op1);      else	common = 1;      break;    case MULT_EXPR:      common = 1;      break;    case TRUNC_DIV_EXPR:    case CEIL_DIV_EXPR:    case FLOOR_DIV_EXPR:    case ROUND_DIV_EXPR:    case EXACT_DIV_EXPR:      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE	   || code0 == COMPLEX_TYPE)	  && (code1 == INTEGER_TYPE || code1 == REAL_TYPE	      || code1 == COMPLEX_TYPE))	{	  if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))	    resultcode = RDIV_EXPR;	  else	    {	      /* Although it would be tempting to shorten always here, that		 loses on some targets, since the modulo instruction is		 undefined if the quotient can't be represented in the		 computation mode.  We shorten only if unsigned or if		 dividing by something we know != -1.  */	      shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))			 || (TREE_CODE (op1) == INTEGER_CST			     && (TREE_INT_CST_LOW (op1) != -1				 || TREE_INT_CST_HIGH (op1) != -1)));	    }	  common = 1;	}      break;    case BIT_AND_EXPR:    case BIT_ANDTC_EXPR:    case BIT_IOR_EXPR:    case BIT_XOR_EXPR:      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)	shorten = -1;      /* If one operand is a constant, and the other is a short type	 that has been converted to an int,	 really do the work in the short type and then convert the	 result to int.  If we are lucky, the constant will be 0 or 1	 in the short type, making the entire operation go away.  */      if (TREE_CODE (op0) == INTEGER_CST	  && TREE_CODE (op1) == NOP_EXPR	  && TYPE_PRECISION (type1) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))	  && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op1, 0))))	{	  final_type = result_type;	  op1 = TREE_OPERAND (op1, 0);	  result_type = TREE_TYPE (op1);	}      if (TREE_CODE (op1) == INTEGER_CST	  && TREE_CODE (op0) == NOP_EXPR	  && TYPE_PRECISION (type0) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))	  && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))	{	  final_type = result_type;	  op0 = TREE_OPERAND (op0, 0);	  result_type = TREE_TYPE (op0);	}      break;    case TRUNC_MOD_EXPR:    case FLOOR_MOD_EXPR:      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)	{	  /* Although it would be tempting to shorten always here, that loses	     on some targets, since the modulo instruction is undefined if the	     quotient can't be represented in the computation mode.  We shorten	     only if unsigned or if dividing by something we know != -1.  */	  shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))		     || (TREE_CODE (op1) == INTEGER_CST			 && (TREE_INT_CST_LOW (op1) !

⌨️ 快捷键说明

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