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

📄 c-typeck.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	  if (TYPE_NAME (cur_type) != 0	      && TREE_CODE (cur_type) != INTEGER_TYPE	      && !(TREE_CODE (cur_type) == POINTER_TYPE		   && TREE_CODE (TREE_TYPE (cur_type)) == INTEGER_TYPE)	      && DECL_NAME (TYPE_NAME (cur_type)) != 0)	    that = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (cur_type)));	  /* A nameless type can't possibly match what the format wants.	     So there will be a warning for it.	     Make up a string to describe vaguely what it is.  */	  if (that == 0)	    {	      if (TREE_CODE (cur_type) == POINTER_TYPE)		that = "pointer";	      else		that = "different type";	    }	  if (strcmp (this, that) != 0)	    {	      sprintf (message, "%s format, %s arg (arg %d)",			this, that, arg_num);	      warning (message);	    }	}    }}/* 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.  */treebuild_function_call (function, params)     tree function, params;{  register tree fntype;  register tree coerced_params;  tree name = NULL_TREE;  /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */  STRIP_TYPE_NOPS (function);  /* Convert anything with function type to a pointer-to-function.  */  if (TREE_CODE (function) == FUNCTION_DECL)    {      name = DECL_NAME (function);      /* Differs from default_conversion by not setting TREE_ADDRESSABLE	 (because calling an inline function does not mean the function	 needs to be separately compiled).  */      fntype = build_type_variant (TREE_TYPE (function),				   TREE_READONLY (function),				   TREE_THIS_VOLATILE (function));      function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);    }  else    function = default_conversion (function);  fntype = TREE_TYPE (function);  if (TREE_CODE (fntype) == ERROR_MARK)    return error_mark_node;  if (!(TREE_CODE (fntype) == POINTER_TYPE	&& TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))    {      error ("called object is not a function");      return error_mark_node;    }  /* fntype now gets the type of function pointed to.  */  fntype = TREE_TYPE (fntype);  /* Convert the parameters to the types declared in the     function prototype, or apply default promotions.  */  coerced_params    = convert_arguments (TYPE_ARG_TYPES (fntype), params, name);  /* Check for errors in format strings.  */  if (warn_format && name != 0)    {      unsigned int i;      /* See if this function is a format function.  */      for (i = 0; i < function_info_entries; i++)	if (function_info_table[i].function_ident == name)	  {	    register char *message;	    /* If so, check it.  */	    check_format (&function_info_table[i], coerced_params);	    break;	  }    }  /* Recognize certain built-in functions so we can make tree-codes     other than CALL_EXPR.  We do this when it enables fold-const.c     to do something useful.  */  if (TREE_CODE (function) == ADDR_EXPR      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL      && DECL_BUILT_IN (TREE_OPERAND (function, 0)))    switch (DECL_FUNCTION_CODE (TREE_OPERAND (function, 0)))      {      case BUILT_IN_ABS:      case BUILT_IN_LABS:      case BUILT_IN_FABS:	if (coerced_params == 0)	  return integer_zero_node;	return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);      }  {    register tree result      = build (CALL_EXPR, TREE_TYPE (fntype),	       function, coerced_params, NULL_TREE);    TREE_SIDE_EFFECTS (result) = 1;    if (TREE_TYPE (result) == void_type_node)      return result;    return require_complete_type (result);  }}/* Convert the argument expressions in the list VALUES   to the types in the list TYPELIST.  The result is a list of converted   argument expressions.   If TYPELIST is exhausted, or when an element has NULL as its type,   perform the default conversions.   PARMLIST is the chain of parm decls for the function being called.   It may be 0, if that info is not available.   It is used only for generating error messages.   NAME is an IDENTIFIER_NODE or 0.  It is used only for error messages.   This is also where warnings about wrong number of args are generated.   Both VALUES and the returned value are chains of TREE_LIST nodes   with the elements of the list in the TREE_VALUE slots of those nodes.  */static treeconvert_arguments (typelist, values, name)     tree typelist, values, name;{  register tree typetail, valtail;  register tree result = NULL;  int parmnum;  /* Scan the given expressions and types, producing individual     converted arguments and pushing them on RESULT in reverse order.  */  for (valtail = values, typetail = typelist, parmnum = 0;       valtail;       valtail = TREE_CHAIN (valtail), parmnum++)    {      register tree type = typetail ? TREE_VALUE (typetail) : 0;      register tree val = TREE_VALUE (valtail);      if (type == void_type_node)	{	  if (name)	    error ("too many arguments to function `%s'",		   IDENTIFIER_POINTER (name));	  else	    error ("too many arguments to function");	  break;	}      /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */      /* Do not use STRIP_NOPS here!  We do not want an enumerator with value 0	 to convert automatically to a pointer.  */      if (TREE_CODE (val) == NON_LVALUE_EXPR)	val = TREE_OPERAND (val, 0);      if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE	  || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE)	val = default_conversion (val);      val = require_complete_type (val);      if (type != 0)	{	  /* Formal parm type is specified by a function prototype.  */	  tree parmval;	  if (TYPE_SIZE (type) == 0)	    {	      error ("type of formal parameter %d is incomplete", parmnum + 1);	      parmval = val;	    }	  else	    {	      tree parmname;#ifdef PROMOTE_PROTOTYPES	      /* Rather than truncating and then reextending,		 convert directly to int, if that's the type we will want.  */	      if (! flag_traditional		  && TREE_CODE (type) == INTEGER_TYPE		  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))		type = integer_type_node;#endif#if 0 /* This turns out not to win--there's no way to write a prototype	 for a function whose arg type is a union with no tag.  */	      /* Nameless union automatically casts the types it contains.  */	      if (TREE_CODE (type) == UNION_TYPE && TYPE_NAME (type) == 0)		{		  tree field;		  for (field = TYPE_FIELDS (type); field;		       field = TREE_CHAIN (field))		    if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),				   TYPE_MAIN_VARIANT (TREE_TYPE (val))))		      break;		  if (field)		    val = build1 (CONVERT_EXPR, type, val);		}#endif	      /* Optionally warn about conversions that		 differ from the default conversions.  */	      if (warn_conversion)		{		  int formal_prec = TYPE_PRECISION (type);		  if (TREE_CODE (type) != REAL_TYPE		      && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)		    warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1);		  else if (TREE_CODE (type) == REAL_TYPE		      && TREE_CODE (TREE_TYPE (val)) != REAL_TYPE)		    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)) == 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 ((TREE_CODE (type) == INTEGER_TYPE			    || TREE_CODE (type) == ENUMERAL_TYPE)			   && (TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE			       || TREE_CODE (TREE_TYPE (val)) == ENUMERAL_TYPE))		    {		      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.  */			;		      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.  */			;		      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  */						name, parmnum + 1);	      #ifdef PROMOTE_PROTOTYPES	      if (TREE_CODE (type) == INTEGER_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 |");	}      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 ^");	}      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 &");	}    }  /* 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");  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);      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.  */tr

⌨️ 快捷键说明

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