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

📄 cp-typeck.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Build expressions with type checking for C++ compiler.   Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.   Hacked by Michael Tiemann (tiemann@cygnus.com)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 and 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).  */extern void error ();extern void warning ();#include "config.h"#include <stdio.h>#include "tree.h"#include "rtl.h"#include "cp-tree.h"#include "flags.h"int mark_addressable ();static tree convert_for_assignment ();/* static */ tree convert_for_initialization ();int compparms ();static int self_promoting_args_p ();int comp_target_types ();extern tree shorten_compare ();void warn_for_assignment ();extern void binary_op_error ();static tree pointer_int_sum ();static tree pointer_diff ();static tree convert_sequence ();/* static */ tree unary_complex_lvalue ();static void pedantic_lvalue_warning ();tree truthvalue_conversion ();extern void readonly_warning_or_error ();extern rtx original_result_rtx;/* Return the target type of TYPE, which meas return T for:   T*, T&, T[], T (...), and otherwise, just T.  */treetarget_type (type)     tree type;{  if (TREE_CODE (type) == REFERENCE_TYPE)    type = TREE_TYPE (type);  while (TREE_CODE (type) == POINTER_TYPE	 || TREE_CODE (type) == ARRAY_TYPE	 || TREE_CODE (type) == FUNCTION_TYPE	 || TREE_CODE (type) == METHOD_TYPE	 || TREE_CODE (type) == OFFSET_TYPE)    type = TREE_TYPE (type);  return type;}/* 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;  /* If we see X::Y, we build an OFFSET_TYPE which has     not been laid out.  Try to avoid an error by interpreting     it as this->X::Y, if reasonable.  */  if (TREE_CODE (value) == OFFSET_REF      && C_C_D != 0      && TREE_OPERAND (value, 0) == C_C_D)    {      tree base, member = TREE_OPERAND (value, 1);      tree basetype = TYPE_OFFSET_BASETYPE (type);      my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305);      base = convert_pointer_to (basetype, current_class_decl);      value = build (COMPONENT_REF, TREE_TYPE (member),		     build_indirect_ref (base, 0), member);      return require_complete_type (value);    }  incomplete_type_error (value, type);  return error_mark_node;}/* Return truthvalue of whether type of EXP is instantiated.  */inttype_unknown_p (exp)     tree exp;{  return (TREE_CODE (exp) == TREE_LIST	  || TREE_TYPE (exp) == unknown_type_node	  || (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE	      && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node));}/* Do `exp = require_instantiated_type (type, exp);' to make sure EXP   does not have an uninstantiated type.   TYPE is type to instantiate with, if uninstantiated.  */treerequire_instantiated_type (type, exp, errval)     tree type, exp, errval;{  if (TREE_TYPE (exp) == unknown_type_node      || (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE	  && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node))    {      exp = instantiate_type (type, exp, 1);      if (TREE_TYPE (exp) == error_mark_node)	return errval;    }  return exp;}/* 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);  /* @@ Must do member pointers here.  */  return build_type_variant (type, constflag, volflag);}/* Return the common type of two parameter lists.   We assume that comptypes has already been done and returned 1;   if that isn't so, this may crash.   As an optimization, free the space we allocate if the parameter   lists are already common.  */treecommonparms (p1, p2)     tree p1, p2;{  tree oldargs = p1, newargs, n;  int i, len;  int any_change = 0;  char *first_obj = (char *) oballoc (0);  len = list_length (p1);  newargs = tree_last (p1);  if (newargs == void_list_node)    i = 1;  else    {      i = 0;      newargs = 0;    }  for (; i < len; i++)    newargs = tree_cons (NULL_TREE, NULL_TREE, newargs);  n = newargs;  for (i = 0; p1;       p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n), i++)    {      if (TREE_PURPOSE (p1) && !TREE_PURPOSE (p2))	{	  /* We used to give a warning here that advised about a default	     argument being given in the prototype but not in the function's	     declaration.  It's best not to bother.  */	  TREE_PURPOSE (n) = TREE_PURPOSE (p1);	  any_change = 1;	}      else if (! TREE_PURPOSE (p1))	{	  if (TREE_PURPOSE (p2))	    {	      TREE_PURPOSE (n) = TREE_PURPOSE (p2);	      any_change = 1;	    }	}      else	{	  int cmp = simple_cst_equal (TREE_PURPOSE (p1), TREE_PURPOSE (p2));	  if (cmp < 0)	    my_friendly_abort (111);	  if (cmp == 0)	    {	      error ("redeclaration of default argument %d", i);	      any_change = 1;	    }	  TREE_PURPOSE (n) = TREE_PURPOSE (p2);	}      if (TREE_VALUE (p1) != TREE_VALUE (p2))	{	  any_change = 1;	  TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2));	}      else	TREE_VALUE (n) = TREE_VALUE (p1);    }  if (! any_change)    {      obfree (first_obj);      return oldargs;    }  return newargs;}/* 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.   This is the type for the result of most arithmetic operations   if the operands have the given two types.   We do not deal with enumeral types here because they have already been   converted to integer 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:    case REFERENCE_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));	target = build_type_variant (target, constp, volatilep);	if (code1 == POINTER_TYPE)	  return build_pointer_type (target);	else	  return build_reference_type (target);      }#if 0    case POINTER_TYPE:      return build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));    case REFERENCE_TYPE:      return build_reference_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);	tree rval, raises;	/* Save space: see if the result is identical to one of the args.  */	if (valtype == TREE_TYPE (t1) && ! p2)	  return t1;	if (valtype == TREE_TYPE (t2) && ! p1)	  return t2;	/* Simple way if one arg fails to specify argument types.  */	if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)	  {	    rval = build_function_type (valtype, p2);	    if (raises = TYPE_RAISES_EXCEPTIONS (t2))	      rval = build_exception_variant (NULL_TREE, rval, raises);	    return rval;	  }	raises = TYPE_RAISES_EXCEPTIONS (t1);	if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)	  {	    rval = build_function_type (valtype, p1);	    if (raises)	      rval = build_exception_variant (NULL_TREE, rval, raises);	    return rval;	  }	rval = build_function_type (valtype, commonparms (p1, p2));	return build_exception_variant (NULL_TREE, rval, raises);      }    case RECORD_TYPE:    case UNION_TYPE:      my_friendly_assert (TYPE_MAIN_VARIANT (t1) == t1			  && TYPE_MAIN_VARIANT (t2) == t2, 306);      if (binfo_or_else (t1, t2))	return t1;      compiler_error ("common_type called with uncommon aggregate types");      return t1;    case METHOD_TYPE:      if (TYPE_METHOD_BASETYPE (t1) == TYPE_METHOD_BASETYPE (t2)	  && TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))	{	  /* Get this value the long way, since TYPE_METHOD_BASETYPE	     is just the main variant of this.  */	  tree basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t1)));	  tree raises, t3;	  raises = TYPE_RAISES_EXCEPTIONS (t1);	  /* If this was a member function type, get back to the	     original type of type member function (i.e., without	     the class instance variable up front.  */	  t1 = build_function_type (TREE_TYPE (t1), TREE_CHAIN (TYPE_ARG_TYPES (t1)));	  t2 = build_function_type (TREE_TYPE (t2), TREE_CHAIN (TYPE_ARG_TYPES (t2)));	  t3 = common_type (t1, t2);	  t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3));	  return build_exception_variant (basetype, t3, raises);	}      compiler_error ("common_type called with uncommon method types");      return t1;    case OFFSET_TYPE:      if (TYPE_OFFSET_BASETYPE (t1) == TYPE_OFFSET_BASETYPE (t2)	  && TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))	{	  tree basetype = TYPE_OFFSET_BASETYPE (t1);	  return build_offset_type (basetype,				    common_type (TREE_TYPE (t1), TREE_TYPE (t2)));	}      compiler_error ("common_type called with uncommon member types");      return t1;    default:      return t1;    }}/* Return 1 if TYPE1 and TYPE2 raise the same exceptions.  */intcompexcepttypes (t1, t2, strict)

⌨️ 快捷键说明

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