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

📄 c-typeck.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Build expressions with type checking for C compiler.   Copyright (C) 1987, 88, 91, 92, 93, 94, 1995 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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, 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"#include "output.h"/* Nonzero if we've already printed a "missing braces around initializer"   message within this initializer.  */static int missing_braces_mentioned;extern char *index ();extern char *rindex ();static tree quality_type		PROTO((tree, tree));static int comp_target_types		PROTO((tree, tree));static int function_types_compatible_p	PROTO((tree, tree));static int type_lists_compatible_p	PROTO((tree, tree));static int self_promoting_type_p	PROTO((tree));static tree decl_constant_value		PROTO((tree));static tree lookup_field		PROTO((tree, tree, tree *));static tree convert_arguments		PROTO((tree, tree, tree, tree));static tree pointer_int_sum		PROTO((enum tree_code, tree, tree));static tree pointer_diff		PROTO((tree, tree));static tree unary_complex_lvalue	PROTO((enum tree_code, tree));static void pedantic_lvalue_warning	PROTO((enum tree_code));static tree internal_build_compound_expr PROTO((tree, int));static tree convert_for_assignment	PROTO((tree, tree, char *, tree,					       tree, int));static void warn_for_assignment		PROTO((char *, char *, tree, int));static tree valid_compound_expr_initializer PROTO((tree, tree));static void push_string			PROTO((char *));static void push_member_name		PROTO((tree));static void push_array_bounds		PROTO((int));static int spelling_length		PROTO((void));static char *print_spelling		PROTO((char *));static char *get_spelling		PROTO((char *));static void warning_init		PROTO((char *, char *,					       char *));static tree digest_init			PROTO((tree, tree, int, int));static void check_init_type_bitfields	PROTO((tree));static void output_init_element		PROTO((tree, tree, tree, int));static void output_pending_init_elements PROTO((int));/* 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;  tree attributes;  /* 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;  /* Merge the attributes */  { register tree a1, a2;    a1 = TYPE_ATTRIBUTES (t1);    a2 = TYPE_ATTRIBUTES (t2);    /* Either one unset?  Take the set one.  */    if (!(attributes = a1))       attributes = a2;    /* One that completely contains the other?  Take it.  */    else if (a2 && !attribute_list_contained (a1, a2))       if (attribute_list_contained (a2, a1))	  attributes = a2;       else	{	  /* Pick the longest list, and hang on the other list.  */	  /* ??? For the moment we punt on the issue of attrs with args.  */		  if (list_length (a1) < list_length (a2))	     attributes = a2, a2 = a1;	  for (; a2; a2 = TREE_CHAIN (a2))	    if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),				  attributes) == NULL_TREE)	      {		a1 = copy_node (a2);		TREE_CHAIN (a1) = attributes;		attributes = a1;	      }	}  }  /* 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);  /* If one type is complex, form the common type of the non-complex     components, then make that complex.  Use T1 or T2 if it is the     required type.  */  if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)    {      tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;      tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;      tree subtype = common_type (subtype1, subtype2);      if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)	return build_type_attribute_variant (t1, attributes);      else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)	return build_type_attribute_variant (t2, attributes);      else	return build_type_attribute_variant (build_complex_type (subtype),					     attributes);    }  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 build_type_attribute_variant (t1, attributes);      if (code2 == REAL_TYPE && code1 != REAL_TYPE)	return build_type_attribute_variant (t2, attributes);      /* Both real or both integers; use the one with greater precision.  */      if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))	return build_type_attribute_variant (t1, attributes);      else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))	return build_type_attribute_variant (t2, attributes);      /* Same precision.  Prefer longs to ints even when same size.  */      if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node	  || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)	return build_type_attribute_variant (long_unsigned_type_node,					     attributes);      if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node	  || TYPE_MAIN_VARIANT (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))	     t1 = long_unsigned_type_node;	  else	     t1 = long_integer_type_node;	  return build_type_attribute_variant (t1, attributes);	}      /* Otherwise prefer the unsigned one.  */      if (TREE_UNSIGNED (t1))	return build_type_attribute_variant (t1, attributes);      else	return build_type_attribute_variant (t2, attributes);    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));	t1 = build_pointer_type (c_build_type_variant (target, constp,				 volatilep));	return build_type_attribute_variant (t1, attributes);      }#if 0      t1 = build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));      return build_type_attribute_variant (t1, attributes);#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 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_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);	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 build_type_attribute_variant (t1, attributes);	if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1))	  return build_type_attribute_variant (t2, attributes);	/* Simple way if one arg fails to specify argument types.  */	if (TYPE_ARG_TYPES (t1) == 0)	 {	   t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));	   return build_type_attribute_variant (t1, attributes);	 }	if (TYPE_ARG_TYPES (t2) == 0)	 {	   t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1));	   return build_type_attribute_variant (t1, attributes);	 }	/* 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))

⌨️ 快捷键说明

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