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

📄 typeck.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Handle types for the GNU compiler for the Java(TM) language.   Copyright (C) 1996, 97-98, 1999 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.  Java and all Java-based marks are trademarks or registered trademarksof Sun Microsystems, Inc. in the United States and other countries.The Free Software Foundation is independent of Sun Microsystems, Inc.  *//* Written by Per Bothner <bothner@cygnus.com> */#include "config.h"#include "system.h"#include "tree.h"#include "obstack.h"#include "flags.h"#include "java-tree.h"#include "jcf.h"#include "convert.h"#include "toplev.h"tree * type_map;extern struct obstack permanent_obstack;/* Set the type of the local variable with index SLOT to TYPE. */voidset_local_type (slot, type)     int slot;     tree type;{  int max_locals = DECL_MAX_LOCALS(current_function_decl);  int nslots = TYPE_IS_WIDE (type) ? 2 : 1;  if (slot < 0 || slot + nslots - 1 >= max_locals)    fatal ("invalid local variable index");  type_map[slot] = type;  while (--nslots > 0)    type_map[++slot] = void_type_node;}/* Convert an IEEE real to an integer type.  The result of such a   conversion when the source operand is a NaN isn't defined by   IEEE754, but by the Java language standard: it must be zero.  This   conversion produces something like:      ({ double tmp = expr; (tmp != tmp) ? 0 : (int)tmp; })   */static treeconvert_ieee_real_to_integer (type, expr)     tree type, expr;{  expr = save_expr (expr);  return build (COND_EXPR, type, 		build (NE_EXPR, boolean_type_node, expr, expr),		convert (type, integer_zero_node),		convert_to_integer (type, expr));}  /* Create an expression whose value is that of EXPR,   converted to type TYPE.  The TREE_TYPE of the value   is always TYPE.  This function implements all reasonable   conversions; callers should filter out those that are   not permitted by the language being compiled.  */treeconvert (type, expr)     tree type, expr;{  register enum tree_code code = TREE_CODE (type);  if (do_not_fold)    return build1 (NOP_EXPR, type, expr);  if (type == TREE_TYPE (expr)      || TREE_CODE (expr) == ERROR_MARK)    return expr;  if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)    return error_mark_node;  if (code == VOID_TYPE)    return build1 (CONVERT_EXPR, type, expr);  if (code == BOOLEAN_TYPE)    return fold (convert_to_boolean (type, expr));  if (code == INTEGER_TYPE)    {      if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE#ifdef TARGET_SOFT_FLOAT	  && !TARGET_SOFT_FLOAT#endif	  && !flag_emit_class_files	  && !flag_fast_math	  && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)	return fold (convert_ieee_real_to_integer (type, expr));      else	return fold (convert_to_integer (type, expr));    }	    if (code == REAL_TYPE)    return fold (convert_to_real (type, expr));  if (code == CHAR_TYPE)    return fold (convert_to_char (type, expr));  if (code == POINTER_TYPE)    return fold (convert_to_pointer (type, expr));  error ("conversion to non-scalar type requested");  return error_mark_node;}treeconvert_to_char (type, expr)    tree type, expr;{  return build1 (NOP_EXPR, type, expr);}treeconvert_to_boolean (type, expr)     tree type, expr;{  return build1 (NOP_EXPR, type, expr);}/* 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 ATTRIBUTE_UNUSED;  tree type ATTRIBUTE_UNUSED;{  error ("internal error - use of undefined type");}/* Return a data type that has machine mode MODE.   If the mode is an integer,   then UNSIGNEDP selects between signed and unsigned types.  */treetype_for_mode (mode, unsignedp)     enum machine_mode mode;     int unsignedp;{  if (mode == TYPE_MODE (int_type_node))    return unsignedp ? unsigned_int_type_node : int_type_node;  if (mode == TYPE_MODE (long_type_node))    return unsignedp ? unsigned_long_type_node : long_type_node;  if (mode == TYPE_MODE (short_type_node))    return unsignedp ? unsigned_short_type_node : short_type_node;  if (mode == TYPE_MODE (byte_type_node))    return unsignedp ? unsigned_byte_type_node : byte_type_node;  if (mode == TYPE_MODE (float_type_node))    return float_type_node;  if (mode == TYPE_MODE (double_type_node))    return double_type_node;  return 0;}/* Return an integer type with BITS bits of precision,   that is unsigned if UNSIGNEDP is nonzero, otherwise signed.  */treetype_for_size (bits, unsignedp)     unsigned bits;     int unsignedp;{  if (bits <= TYPE_PRECISION (byte_type_node))    return unsignedp ? unsigned_byte_type_node : byte_type_node;  if (bits <= TYPE_PRECISION (short_type_node))    return unsignedp ? unsigned_short_type_node : short_type_node;  if (bits <= TYPE_PRECISION (int_type_node))    return unsignedp ? unsigned_int_type_node : int_type_node;  if (bits <= TYPE_PRECISION (long_type_node))    return unsignedp ? unsigned_long_type_node : long_type_node;  return 0;}/* Return a type the same as TYPE except unsigned or   signed according to UNSIGNEDP.  */treesigned_or_unsigned_type (unsignedp, type)     int unsignedp;     tree type;{  if (! INTEGRAL_TYPE_P (type))    return type;  if (TYPE_PRECISION (type) == TYPE_PRECISION (int_type_node))    return unsignedp ? unsigned_int_type_node : int_type_node;  if (TYPE_PRECISION (type) == TYPE_PRECISION (byte_type_node))    return unsignedp ? unsigned_byte_type_node : byte_type_node;  if (TYPE_PRECISION (type) == TYPE_PRECISION (short_type_node))    return unsignedp ? unsigned_short_type_node : short_type_node;  if (TYPE_PRECISION (type) == TYPE_PRECISION (long_type_node))    return unsignedp ? unsigned_long_type_node : long_type_node;  return type;}/* Return a signed type the same as TYPE in other respects.  */treesigned_type (type)     tree type;{  return signed_or_unsigned_type (0, type);}/* Return an unsigned type the same as TYPE in other respects.  */treeunsigned_type (type)     tree type;{  return signed_or_unsigned_type (1, type);}/* Mark EXP saying that we need to be able to take the   address of it; it should not be allocated in a register.   Value is 1 if successful.  */intmark_addressable (exp)     tree exp;{  register tree x = exp;  while (1)    switch (TREE_CODE (x))      {      case ADDR_EXPR:      case COMPONENT_REF:      case ARRAY_REF:      case REALPART_EXPR:      case IMAGPART_EXPR:	x = TREE_OPERAND (x, 0);	break;      case TRUTH_ANDIF_EXPR:      case TRUTH_ORIF_EXPR:      case COMPOUND_EXPR:	x = TREE_OPERAND (x, 1);	break;      case COND_EXPR:	return mark_addressable (TREE_OPERAND (x, 1))	  & mark_addressable (TREE_OPERAND (x, 2));      case CONSTRUCTOR:	TREE_ADDRESSABLE (x) = 1;	return 1;      case INDIRECT_REF:	/* We sometimes add a cast *(TYPE*)&FOO to handle type and mode	   incompatibility problems.  Handle this case by marking FOO.  */	if (TREE_CODE (TREE_OPERAND (x, 0)) == NOP_EXPR	    && TREE_CODE (TREE_OPERAND (TREE_OPERAND (x, 0), 0)) == ADDR_EXPR)	  {	    x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);	    break;	  }	if (TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)	  {	    x = TREE_OPERAND (x, 0);	    break;	  }	return 1;      case VAR_DECL:      case CONST_DECL:      case PARM_DECL:      case RESULT_DECL:      case FUNCTION_DECL:	TREE_ADDRESSABLE (x) = 1;#if 0  /* poplevel deals with this now.  */	if (DECL_CONTEXT (x) == 0)	  TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;#endif	/* drops through */      default:	return 1;    }}/* Thorough checking of the arrayness of TYPE.  */intis_array_type_p (type)     tree type;{  return TREE_CODE (type) == POINTER_TYPE    && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE    && TYPE_ARRAY_P (TREE_TYPE (type));}/* Return the length of a Java array type.   Return -1 if the length is unknown or non-constant. */HOST_WIDE_INTjava_array_type_length (array_type)     tree array_type;{  tree arfld;  if (TREE_CODE (array_type) == POINTER_TYPE)    array_type = TREE_TYPE (array_type);  arfld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type)));  if (arfld != NULL_TREE)    {      tree index_type = TYPE_DOMAIN (TREE_TYPE (arfld));      tree high = TYPE_MAX_VALUE (index_type);      if (TREE_CODE (high) == INTEGER_CST)	return TREE_INT_CST_LOW (high) + 1;    }  return -1;}treebuild_prim_array_type (element_type, length)     tree element_type;     HOST_WIDE_INT length;{  tree max_index = build_int_2 (length - 1, 0);  TREE_TYPE (max_index) = sizetype;  return build_array_type (element_type, build_index_type (max_index));}/* Return a Java array type with a given ELEMENT_TYPE and LENGTH.   These are hashed (shared) using IDENTIFIER_SIGNATURE_TYPE.   The LENGTH is -1 if the length is unknown. */treebuild_java_array_type (element_type, length)     tree element_type;     HOST_WIDE_INT length;{  tree sig, t, fld;  char buf[12];  tree elsig = build_java_signature (element_type);  tree el_name = element_type;  sprintf (buf, length >= 0 ? "[%d" : "[", length);  sig = ident_subst (IDENTIFIER_POINTER (elsig), IDENTIFIER_LENGTH (elsig),		     buf, 0, 0, "");  t = IDENTIFIER_SIGNATURE_TYPE (sig);  if (t != NULL_TREE)    return TREE_TYPE (t);  t = make_class ();  IDENTIFIER_SIGNATURE_TYPE (sig) = build_pointer_type (t);  TYPE_ARRAY_P (t) = 1;  if (TREE_CODE (el_name) == POINTER_TYPE)    el_name = TREE_TYPE (el_name);  el_name = TYPE_NAME (el_name);  if (TREE_CODE (el_name) == TYPE_DECL)    el_name = DECL_NAME (el_name);  TYPE_NAME (t) = identifier_subst (el_name, "", '.', '.', "[]");  set_java_signature (t, sig);  set_super_info (0, t, object_type_node, 0);  if (TREE_CODE (element_type) == RECORD_TYPE)    element_type = promote_type (element_type);  TYPE_ARRAY_ELEMENT (t) = element_type;  /* Add length pseudo-field. */  push_obstacks (&permanent_obstack, &permanent_obstack);  fld = build_decl (FIELD_DECL, get_identifier ("length"), int_type_node);  TYPE_FIELDS (t) = fld;  DECL_CONTEXT (fld) = t;  FIELD_PUBLIC (fld) = 1;  FIELD_FINAL (fld) = 1;  if (length >= 0)    {      tree atype = build_prim_array_type (element_type, length);      tree arfld = build_decl (FIELD_DECL, get_identifier ("data"), atype);      DECL_CONTEXT (arfld) = t;      TREE_CHAIN (fld) = arfld;    }  else    TYPE_ALIGN (t) = TYPE_ALIGN (element_type);  pop_obstacks ();  /* We could layout_class, but that loads java.lang.Object prematurely.   * This is called by the parser, and it is a bad idea to do load_class   * in the middle of parsing, because of possible circularity problems. */

⌨️ 快捷键说明

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