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

📄 c-typeck.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* Constants can be used directly unless they're not loadable.  */  if (TREE_CODE (exp) == CONST_DECL)    exp = DECL_INITIAL (exp);  /* Replace a nonvolatile const static variable with its value.  */  else if (optimize	   && TREE_CODE (exp) == VAR_DECL	   && TREE_READONLY (exp)	   && DECL_MODE (exp) != BLKmode)    {      exp = decl_constant_value (exp);      type = TREE_TYPE (exp);    }  /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as     an lvalue.  */  /* Do not use STRIP_NOPS here!  It will remove conversions from pointer     to integer and cause infinite recursion.  */  while (TREE_CODE (exp) == NON_LVALUE_EXPR	 || (TREE_CODE (exp) == NOP_EXPR	     && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))    exp = TREE_OPERAND (exp, 0);  /* Normally convert enums to int,     but convert wide enums to something wider.  */  if (code == ENUMERAL_TYPE)    {      type = type_for_size (MAX (TYPE_PRECISION (type),				 TYPE_PRECISION (integer_type_node)),			    (flag_traditional && TREE_UNSIGNED (type)));      return convert (type, exp);    }  if (C_PROMOTING_INTEGER_TYPE_P (type))    {      /* Traditionally, unsignedness is preserved in default promotions.         Also preserve unsignedness if not really getting any wider.  */      if (TREE_UNSIGNED (type)	  && (flag_traditional	      || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))	return convert (unsigned_type_node, exp);      return convert (integer_type_node, exp);    }  if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node)    return convert (double_type_node, exp);  if (code == VOID_TYPE)    {      error ("void value not ignored as it ought to be");      return error_mark_node;    }  if (code == FUNCTION_TYPE)    {      return build_unary_op (ADDR_EXPR, exp, 0);    }  if (code == ARRAY_TYPE)    {      register tree adr;      tree restype = TREE_TYPE (type);      tree ptrtype;      if (TREE_CODE (exp) == INDIRECT_REF)	return convert (TYPE_POINTER_TO (restype),			TREE_OPERAND (exp, 0));      if (TREE_CODE (exp) == COMPOUND_EXPR)	{	  tree op1 = default_conversion (TREE_OPERAND (exp, 1));	  return build (COMPOUND_EXPR, TREE_TYPE (op1),			TREE_OPERAND (exp, 0), op1);	}      if (!lvalue_p (exp)	  && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))	{	  error ("invalid use of non-lvalue array");	  return error_mark_node;	}      if (TYPE_READONLY (type) || TYPE_VOLATILE (type))	restype = c_build_type_variant (restype, TYPE_READONLY (type),					TYPE_VOLATILE (type));      ptrtype = build_pointer_type (restype);      if (TREE_CODE (exp) == VAR_DECL)	{	  /* ??? This is not really quite correct	     in that the type of the operand of ADDR_EXPR	     is not the target type of the type of the ADDR_EXPR itself.	     Question is, can this lossage be avoided?  */	  adr = build1 (ADDR_EXPR, ptrtype, exp);	  if (mark_addressable (exp) == 0)	    return error_mark_node;	  TREE_CONSTANT (adr) = staticp (exp);	  TREE_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */	  return adr;	}      /* This way is better for a COMPONENT_REF since it can	 simplify the offset for a component.  */      adr = build_unary_op (ADDR_EXPR, exp, 1);      return convert (ptrtype, adr);    }  return exp;}/* Make an expression to refer to the COMPONENT field of   structure or union value DATUM.  COMPONENT is an IDENTIFIER_NODE.  */treebuild_component_ref (datum, component)     tree datum, component;{  register tree type = TREE_TYPE (datum);  register enum tree_code code = TREE_CODE (type);  register tree field = NULL;  register tree ref;  /* 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);	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),	 build_component_ref (TREE_OPERAND (datum, 2), component));    }  /* See if there is a field or component with name COMPONENT.  */  if (code == RECORD_TYPE || code == UNION_TYPE)    {      if (TYPE_SIZE (type) == 0)	{	  incomplete_type_error (NULL_TREE, type);	  return error_mark_node;	}      /* Look up component name in the structure type definition.	 If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers	 to the field elements.  Use a binary search on this array to quickly	 find the element.  Otherwise, do a linear search.  TYPE_LANG_SPECIFIC	 will always be set for structures which have many elements.  */      if (TYPE_LANG_SPECIFIC (type))	{	  int bot, top, half;	  tree *field_array = &TYPE_LANG_SPECIFIC (type)->elts[0];	  field = TYPE_FIELDS (type);	  bot = 0;	  top = TYPE_LANG_SPECIFIC (type)->len;	  while (top - bot > 1)	    {	      int cmp;	      half = (top - bot + 1) >> 1;	      field = field_array[bot+half];	      cmp = (long)DECL_NAME (field) - (long)component;	      if (cmp == 0)		break;	      if (cmp < 0)		bot += half;	      else		top = bot + half;	    }	  if (DECL_NAME (field_array[bot]) == component)	    field = field_array[bot];	  else if (DECL_NAME (field) != component)	    field = 0;	}      else	{	  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))	    {	      if (DECL_NAME (field) == component)		break;	    }	}      if (!field)	{	  error (code == RECORD_TYPE		 ? "structure has no member named `%s'"		 : "union has no member named `%s'",		 IDENTIFIER_POINTER (component));	  return error_mark_node;	}      if (TREE_TYPE (field) == error_mark_node)	return error_mark_node;      ref = build (COMPONENT_REF, TREE_TYPE (field), 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;    }  else if (code != ERROR_MARK)    error ("request for member `%s' in something not a structure or union",	    IDENTIFIER_POINTER (component));  return error_mark_node;}/* 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.  */treebuild_indirect_ref (ptr, errorstring)     tree ptr;     char *errorstring;{  register tree pointer = default_conversion (ptr);  register tree type = TREE_TYPE (pointer);  if (TREE_CODE (type) == POINTER_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);	if (TREE_CODE (t) == VOID_TYPE	    || (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE))	  {	    error ("dereferencing pointer to incomplete type");	    return error_mark_node;	  }	/* We *must* set TREE_READONLY when dereferencing a pointer to const,	   so that we get the proper error message if the result is used	   to assign to.  Also, &* is supposed to be a no-op.	   And ANSI C seems to specify that the type of the result	   should be the const type.  */	/* A de-reference of a pointer to const is not a const.  It is valid	   to change it via some other pointer.  */	TREE_READONLY (ref) = TYPE_READONLY (t);	TREE_SIDE_EFFECTS (ref) = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);	TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);	return ref;      }  else if (TREE_CODE (pointer) != ERROR_MARK)    error ("invalid type argument of `%s'", errorstring);  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).  */treebuild_array_ref (array, index)     tree array, index;{  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;  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);      /* Require integer *after* promotion, for sake of enums.  */      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;	}      if (pedantic && !lvalue_p (array))	{	  if (DECL_REGISTER (array))	    pedwarn ("ANSI C forbids subscripting `register' array");	  else	    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 (PLUS_EXPR, ar, ind, 0),			       "array indexing");  }}/* Check a printf/fprintf/sprintf/scanf/fscanf/sscanf format against PARAMS.  */#define ISDIGIT(c)	((c) >= '0' && (c) <= '9')#define T_I	&integer_type_node#define T_L	&long_integer_type_node#define T_S	&short_integer_type_node#define T_UI	&unsigned_type_node#define T_UL	&long_unsigned_type_node#define T_US	&short_unsigned_type_node#define T_F	&float_type_node#define T_D	&double_type_node#define T_LD	&long_double_type_node#define T_C	&char_type_node#define T_V	&void_type_node#define T_W	&wchar_type_nodetypedef struct{  char *format_chars;  int pointer_count;  /* Type of argument if no length modifier is used.  */  tree *nolen;  /* Type of argument if length modifier for shortening is used.     If NULL, then this modifier is not allowed.  */  tree *hlen;  /* Type of argument if length modifier `l' is used.     If NULL, then this modifier is not allowed.  */  tree *llen;  /* Type of argument if length modifier `L' is used.     If NULL, then this modifier is not allowed.  */  tree *bigllen;  /* List of other modifier characters allowed with these options.  */  char *flag_chars;} format_char_info;static format_char_info print_table[]  = {      { "di",		0,	T_I,	T_I,	T_L,	NULL,	"-wp0 +" },      { "oxX",		0,	T_UI,	T_UI,	T_UL,	NULL,	"-wp0#" },      { "u",		0,	T_UI,	T_UI,	T_UL,	NULL,	"-wp0" },      { "feEgG",	0,	T_D,	NULL,	NULL,	T_LD,	"-wp0 +#" },      { "c",		0,	T_I,	NULL,	T_W,	NULL,	"-w" },      { "C",		0,	T_W,	NULL,	NULL,	NULL,	"-w" },      { "s",		1,	T_C,	NULL,	T_W,	NULL,	"-wp" },

⌨️ 快捷键说明

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