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

📄 c-typeck.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Build expressions with type checking for C compiler.   Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* This file is part of the C front end.   It contains routines to build C expressions given their operands,   including computing the types of the result, C-specific error checks,   and some optimization.   There are also routines to build RETURN_STMT nodes and CASE_STMT nodes,   and to process initializations in declarations (since they work   like a strange sort of assignment).  */#include "config.h"#include <stdio.h>#include "tree.h"#include "c-tree.h"#include "flags.h"extern char *index ();extern char *rindex ();int mark_addressable ();static tree convert_for_assignment ();static void warn_for_assignment ();static int function_types_compatible_p ();static int type_lists_compatible_p ();int self_promoting_args_p ();static int self_promoting_type_p ();static int comp_target_types ();static tree pointer_int_sum ();static tree pointer_diff ();static tree convert_sequence ();static tree unary_complex_lvalue ();static tree process_init_constructor ();static tree convert_arguments ();static char *get_spelling ();tree digest_init ();static void pedantic_lvalue_warning ();tree truthvalue_conversion ();void incomplete_type_error ();void readonly_warning ();/* Do `exp = require_complete_type (exp);' to make sure exp   does not have an incomplete type.  (That includes void types.)  */treerequire_complete_type (value)     tree value;{  tree type = TREE_TYPE (value);  /* First, detect a valid value with a complete type.  */  if (TYPE_SIZE (type) != 0      && type != void_type_node)    return value;  incomplete_type_error (value, type);  return error_mark_node;}/* Print an error message for invalid use of an incomplete type.   VALUE is the expression that was used (or 0 if that isn't known)   and TYPE is the type that was invalid.  */voidincomplete_type_error (value, type)     tree value;     tree type;{  char *errmsg;  /* Avoid duplicate error message.  */  if (TREE_CODE (type) == ERROR_MARK)    return;  if (value != 0 && (TREE_CODE (value) == VAR_DECL		     || TREE_CODE (value) == PARM_DECL))    error ("`%s' has an incomplete type",	   IDENTIFIER_POINTER (DECL_NAME (value)));  else    {    retry:      /* We must print an error message.  Be clever about what it says.  */      switch (TREE_CODE (type))	{	case RECORD_TYPE:	  errmsg = "invalid use of undefined type `struct %s'";	  break;	case UNION_TYPE:	  errmsg = "invalid use of undefined type `union %s'";	  break;	case ENUMERAL_TYPE:	  errmsg = "invalid use of undefined type `enum %s'";	  break;	case VOID_TYPE:	  error ("invalid use of void expression");	  return;	case ARRAY_TYPE:	  if (TYPE_DOMAIN (type))	    {	      type = TREE_TYPE (type);	      goto retry;	    }	  error ("invalid use of array with unspecified bounds");	  return;	default:	  abort ();	}      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)	error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type)));      else	/* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL.  */	error ("invalid use of incomplete typedef `%s'",	       IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));    }}/* Return a variant of TYPE which has all the type qualifiers of LIKE   as well as those of TYPE.  */static treequalify_type (type, like)     tree type, like;{  int constflag = TYPE_READONLY (type) || TYPE_READONLY (like);  int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);  return c_build_type_variant (type, constflag, volflag);}/* Return the common type of two types.   We assume that comptypes has already been done and returned 1;   if that isn't so, this may crash.  In particular, we assume that qualifiers   match.   This is the type for the result of most arithmetic operations   if the operands have the given two types.  */treecommon_type (t1, t2)     tree t1, t2;{  register enum tree_code code1;  register enum tree_code code2;  /* Save time if the two types are the same.  */  if (t1 == t2) return t1;  /* If one type is nonsense, use the other.  */  if (t1 == error_mark_node)    return t2;  if (t2 == error_mark_node)    return t1;  /* 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);  code1 = TREE_CODE (t1);  code2 = TREE_CODE (t2);  switch (code1)    {    case INTEGER_TYPE:    case REAL_TYPE:      /* If only one is real, use it as the result.  */      if (code1 == REAL_TYPE && code2 != REAL_TYPE)	return t1;      if (code2 == REAL_TYPE && code1 != REAL_TYPE)	return t2;      /* Both real or both integers; use the one with greater precision.  */      if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))	return t1;      else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))	return t2;      /* Same precision.  Prefer longs to ints even when same size.  */      if (t1 == long_unsigned_type_node	  || t2 == long_unsigned_type_node)	return long_unsigned_type_node;      if (t1 == long_integer_type_node	  || t2 == long_integer_type_node)	{	  /* But preserve unsignedness from the other type,	     since long cannot hold all the values of an unsigned int.  */	  if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))	    return long_unsigned_type_node;	  return long_integer_type_node;	}      /* Otherwise prefer the unsigned one.  */      if (TREE_UNSIGNED (t1))	return t1;      else return t2;    case POINTER_TYPE:      /* For two pointers, do this recursively on the target type,	 and combine the qualifiers of the two types' targets.  */      /* This code was turned off; I don't know why.	 But ANSI C specifies doing this with the qualifiers.	 So I turned it on again.  */      {	tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),				   TYPE_MAIN_VARIANT (TREE_TYPE (t2)));	int constp	  = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));	int volatilep	  = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));	return build_pointer_type (c_build_type_variant (target, constp, volatilep));      }#if 0      return build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));#endif    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 t1;	if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))	  return t2;	/* Merge the element types, and have a size if either arg has one.  */	return build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));      }    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);	int len;	tree newargs, n;	int i;	/* Save space: see if the result is identical to one of the args.  */	if (valtype == TREE_TYPE (t1) && ! TYPE_ARG_TYPES (t2))	  return t1;	if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1))	  return t2;	/* Simple way if one arg fails to specify argument types.  */	if (TYPE_ARG_TYPES (t1) == 0)	  return build_function_type (valtype, TYPE_ARG_TYPES (t2));	if (TYPE_ARG_TYPES (t2) == 0)	  return build_function_type (valtype, TYPE_ARG_TYPES (t1));	/* If both args specify argument types, we must merge the two	   lists, argument by argument.  */	len = list_length (p1);	newargs = 0;	for (i = 0; i < len; i++)	  newargs = tree_cons (NULL_TREE, NULL_TREE, newargs);	n = newargs;	for (; p1;	     p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n))	  {	    /* A null type means arg type is not specified.	       Take whatever the other function type has.  */	    if (TREE_VALUE (p1) == 0)	      {		TREE_VALUE (n) = TREE_VALUE (p2);		goto parm_done;	      }	    if (TREE_VALUE (p2) == 0)	      {		TREE_VALUE (n) = TREE_VALUE (p1);		goto parm_done;	      }	      	    /* Given  wait (union {union wait *u; int *i} *)	       and  wait (union wait *),	       prefer  union wait *  as type of parm.  */	    if (TREE_CODE (TREE_VALUE (p1)) == UNION_TYPE		&& TREE_VALUE (p1) != TREE_VALUE (p2))	      {		tree memb;		for (memb = TYPE_FIELDS (TREE_VALUE (p1));		     memb; memb = TREE_CHAIN (memb))		  if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2)))		    {		      TREE_VALUE (n) = TREE_VALUE (p2);		      if (pedantic)			pedwarn ("function types not truly compatible in ANSI C");		      goto parm_done;		    }	      }	    if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE		&& TREE_VALUE (p2) != TREE_VALUE (p1))	      {		tree memb;		for (memb = TYPE_FIELDS (TREE_VALUE (p2));		     memb; memb = TREE_CHAIN (memb))		  if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1)))		    {		      TREE_VALUE (n) = TREE_VALUE (p1);		      if (pedantic)			pedwarn ("function types not truly compatible in ANSI C");		      goto parm_done;		    }	      }	    TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2));	  parm_done: ;	  }	return build_function_type (valtype, newargs);      }    default:      return t1;    }}/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment   or various other operations.  Return 2 if they are compatible   but a warning may be needed if you use them together.  */intcomptypes (type1, type2)     tree type1, type2;{  register tree t1 = type1;  register tree t2 = type2;  /* Suppress errors caused by previously reported errors.  */  if (t1 == t2 || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)    return 1;  /* 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;  /* Different classes of types can't be compatible.  */  if (TREE_CODE (t1) != TREE_CODE (t2)) return 0;  /* Qualifiers must match.  */  if (TYPE_READONLY (t1) != TYPE_READONLY (t2))    return 0;  if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))    return 0;  /* If generating auxiliary info, allow for two different type nodes which     have essentially the same definition.  */  if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))    return 1;  switch (TREE_CODE (t1))    {    case POINTER_TYPE:      return (TREE_TYPE (t1) == TREE_TYPE (t2)	      ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));    case FUNCTION_TYPE:      return function_types_compatible_p (t1, t2);    case ARRAY_TYPE:      {	/* 1 if no need for warning yet, 2 if warning cause has been seen.  */	int val = 1;	tree d1 = TYPE_DOMAIN (t1);	tree d2 = TYPE_DOMAIN (t2);	/* Target types must match incl. qualifiers.  */	if (TREE_TYPE (t1) != TREE_TYPE (t2)	    && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2))))	  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 val;	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))))		? val : 0);

⌨️ 快捷键说明

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