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

📄 tree.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Language-dependent node constructors for parse phase of GNU compiler.   Copyright (C) 1987, 88, 92, 93, 94, 1995 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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include <stdio.h>#include "obstack.h"#include "tree.h"#include "cp-tree.h"#include "flags.h"#include "rtl.h"#define CEIL(x,y) (((x) + (y) - 1) / (y))/* Return nonzero if REF is an lvalue valid for this language.   Lvalues can be assigned, unless they have TREE_READONLY.   Lvalues can have their address taken, unless they have DECL_REGISTER.  */intreal_lvalue_p (ref)     tree ref;{  if (! language_lvalue_valid (ref))    return 0;    if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)    return 1;  if (ref == current_class_decl && flag_this_is_variable <= 0)    return 0;  switch (TREE_CODE (ref))    {      /* preincrements and predecrements are valid lvals, provided	 what they refer to are valid lvals. */    case PREINCREMENT_EXPR:    case PREDECREMENT_EXPR:    case COMPONENT_REF:    case SAVE_EXPR:      return real_lvalue_p (TREE_OPERAND (ref, 0));    case STRING_CST:      return 1;    case VAR_DECL:      if (TREE_READONLY (ref) && ! TREE_STATIC (ref)	  && DECL_LANG_SPECIFIC (ref)	  && DECL_IN_AGGR_P (ref))	return 0;    case INDIRECT_REF:    case ARRAY_REF:    case PARM_DECL:    case RESULT_DECL:    case ERROR_MARK:      if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE	  && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)	return 1;      break;    case WITH_CLEANUP_EXPR:      return real_lvalue_p (TREE_OPERAND (ref, 0));      /* A currently unresolved scope ref.  */    case SCOPE_REF:      my_friendly_abort (103);    case OFFSET_REF:      if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)	return 1;      return real_lvalue_p (TREE_OPERAND (ref, 0))	&& real_lvalue_p (TREE_OPERAND (ref, 1));      break;    case COND_EXPR:      return (real_lvalue_p (TREE_OPERAND (ref, 1))	      && real_lvalue_p (TREE_OPERAND (ref, 2)));    case MODIFY_EXPR:      return 1;    case COMPOUND_EXPR:      return real_lvalue_p (TREE_OPERAND (ref, 1));    case MAX_EXPR:    case MIN_EXPR:      return (real_lvalue_p (TREE_OPERAND (ref, 0))	      && real_lvalue_p (TREE_OPERAND (ref, 1)));    }  return 0;}intlvalue_p (ref)     tree ref;{  if (! language_lvalue_valid (ref))    return 0;    if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)    return 1;  if (ref == current_class_decl && flag_this_is_variable <= 0)    return 0;  switch (TREE_CODE (ref))    {      /* preincrements and predecrements are valid lvals, provided	 what they refer to are valid lvals. */    case PREINCREMENT_EXPR:    case PREDECREMENT_EXPR:    case COMPONENT_REF:    case SAVE_EXPR:      return lvalue_p (TREE_OPERAND (ref, 0));    case STRING_CST:      return 1;    case VAR_DECL:      if (TREE_READONLY (ref) && ! TREE_STATIC (ref)	  && DECL_LANG_SPECIFIC (ref)	  && DECL_IN_AGGR_P (ref))	return 0;    case INDIRECT_REF:    case ARRAY_REF:    case PARM_DECL:    case RESULT_DECL:    case ERROR_MARK:      if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE	  && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)	return 1;      break;    case WITH_CLEANUP_EXPR:      return lvalue_p (TREE_OPERAND (ref, 0));    case TARGET_EXPR:      return 1;    case CALL_EXPR:      if (IS_AGGR_TYPE (TREE_TYPE (ref)))	return 1;      break;      /* A currently unresolved scope ref.  */    case SCOPE_REF:      my_friendly_abort (103);    case OFFSET_REF:      if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)	return 1;      return lvalue_p (TREE_OPERAND (ref, 0))	&& lvalue_p (TREE_OPERAND (ref, 1));      break;    case COND_EXPR:      return (lvalue_p (TREE_OPERAND (ref, 1))	      && lvalue_p (TREE_OPERAND (ref, 2)));    case MODIFY_EXPR:      return 1;    case COMPOUND_EXPR:      return lvalue_p (TREE_OPERAND (ref, 1));    case MAX_EXPR:    case MIN_EXPR:      return (lvalue_p (TREE_OPERAND (ref, 0))	      && lvalue_p (TREE_OPERAND (ref, 1)));    }  return 0;}/* Return nonzero if REF is an lvalue valid for this language;   otherwise, print an error message and return zero.  */intlvalue_or_else (ref, string)     tree ref;     char *string;{  int win = lvalue_p (ref);  if (! win)    error ("non-lvalue in %s", string);  return win;}/* INIT is a CALL_EXPR which needs info about its target.   TYPE is the type that this initialization should appear to have.   Build an encapsulation of the initialization to perform   and return it so that it can be processed by language-independent   and language-specific expression expanders.   If WITH_CLEANUP_P is nonzero, we build a cleanup for this expression.   Otherwise, cleanups are not built here.  For example, when building   an initialization for a stack slot, since the called function handles   the cleanup, we would not want to do it here.  */treebuild_cplus_new (type, init, with_cleanup_p)     tree type;     tree init;     int with_cleanup_p;{  tree slot;  tree rval;  slot = build (VAR_DECL, type);  layout_decl (slot, 0);  rval = build (NEW_EXPR, type,		TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);  TREE_SIDE_EFFECTS (rval) = 1;  TREE_ADDRESSABLE (rval) = 1;  rval = build (TARGET_EXPR, type, slot, rval, 0);  TREE_SIDE_EFFECTS (rval) = 1;  TREE_ADDRESSABLE (rval) = 1;#if 0  if (with_cleanup_p && TYPE_NEEDS_DESTRUCTOR (type))    {      TREE_OPERAND (rval, 2) = error_mark_node;      rval = build (WITH_CLEANUP_EXPR, type, rval, 0,		    build_delete (build_pointer_type (type),				  build_unary_op (ADDR_EXPR, slot, 0),				  integer_two_node,				  LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0));      TREE_SIDE_EFFECTS (rval) = 1;      TREE_ADDRESSABLE (rval) = 1;    }#endif  return rval;}/* Recursively search EXP for CALL_EXPRs that need cleanups and replace   these CALL_EXPRs with tree nodes that will perform the cleanups.  */treebreak_out_cleanups (exp)     tree exp;{  tree tmp = exp;  if (TREE_CODE (tmp) == CALL_EXPR      && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp)))    return build_cplus_new (TREE_TYPE (tmp), tmp, 1);  while (TREE_CODE (tmp) == NOP_EXPR	 || TREE_CODE (tmp) == CONVERT_EXPR	 || TREE_CODE (tmp) == NON_LVALUE_EXPR)    {      if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR	  && TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0))))	{	  TREE_OPERAND (tmp, 0)	    = build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),			       TREE_OPERAND (tmp, 0), 1);	  break;	}      else	tmp = TREE_OPERAND (tmp, 0);    }  return exp;}/* Recursively perform a preorder search EXP for CALL_EXPRs, making   copies where they are found.  Returns a deep copy all nodes transitively   containing CALL_EXPRs.  */treebreak_out_calls (exp)     tree exp;{  register tree t1, t2;  register enum tree_code code;  register int changed = 0;  register int i;  if (exp == NULL_TREE)    return exp;  code = TREE_CODE (exp);  if (code == CALL_EXPR)    return copy_node (exp);  /* Don't try and defeat a save_expr, as it should only be done once. */    if (code == SAVE_EXPR)       return exp;  switch (TREE_CODE_CLASS (code))    {    default:      abort ();    case 'c':  /* a constant */    case 't':  /* a type node */    case 'x':  /* something random, like an identifier or an ERROR_MARK.  */      return exp;    case 'd':  /* A decl node */#if 0                               /* This is bogus.  jason 9/21/94 */      t1 = break_out_calls (DECL_INITIAL (exp));      if (t1 != DECL_INITIAL (exp))	{	  exp = copy_node (exp);	  DECL_INITIAL (exp) = t1;	}#endif      return exp;    case 'b':  /* A block node */      {	/* Don't know how to handle these correctly yet.   Must do a	   break_out_calls on all DECL_INITIAL values for local variables,	   and also break_out_calls on all sub-blocks and sub-statements.  */	abort ();      }      return exp;    case 'e':  /* an expression */    case 'r':  /* a reference */    case 's':  /* an expression with side effects */      for (i = tree_code_length[(int) code] - 1; i >= 0; i--)	{	  t1 = break_out_calls (TREE_OPERAND (exp, i));	  if (t1 != TREE_OPERAND (exp, i))	    {	      exp = copy_node (exp);	      TREE_OPERAND (exp, i) = t1;	    }	}      return exp;    case '<':  /* a comparison expression */    case '2':  /* a binary arithmetic expression */      t2 = break_out_calls (TREE_OPERAND (exp, 1));      if (t2 != TREE_OPERAND (exp, 1))	changed = 1;    case '1':  /* a unary arithmetic expression */      t1 = break_out_calls (TREE_OPERAND (exp, 0));      if (t1 != TREE_OPERAND (exp, 0))	changed = 1;      if (changed)	{	  if (tree_code_length[(int) code] == 1)	    return build1 (code, TREE_TYPE (exp), t1);	  else	    return build (code, TREE_TYPE (exp), t1, t2);	}      return exp;    }}extern struct obstack *current_obstack;extern struct obstack permanent_obstack, class_obstack;extern struct obstack *saveable_obstack;/* Here is how primitive or already-canonicalized types' hash   codes are made.  MUST BE CONSISTENT WITH tree.c !!! */#define TYPE_HASH(TYPE) ((HOST_WIDE_INT) (TYPE) & 0777777)/* Construct, lay out and return the type of methods belonging to class   BASETYPE and whose arguments are described by ARGTYPES and whose values   are described by RETTYPE.  If each type exists already, reuse it.  */treebuild_cplus_method_type (basetype, rettype, argtypes)     tree basetype, rettype, argtypes;{  register tree t;  tree ptype;  int hashcode;  /* Make a node of the sort we want.  */  t = make_node (METHOD_TYPE);  TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);  TREE_TYPE (t) = rettype;  if (IS_SIGNATURE (basetype))    ptype = build_signature_pointer_type (TYPE_MAIN_VARIANT (basetype),					  TYPE_READONLY (basetype),					  TYPE_VOLATILE (basetype));  else    ptype = build_pointer_type (basetype);  /* The actual arglist for this function includes a "hidden" argument     which is "this".  Put it into the list of argument types.  */  argtypes = tree_cons (NULL_TREE, ptype, argtypes);  TYPE_ARG_TYPES (t) = argtypes;  TREE_SIDE_EFFECTS (argtypes) = 1;  /* Mark first argtype as "artificial".  */  /* If we already have such a type, use the old one and free this one.     Note that it also frees up the above cons cell if found.  */  hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);  t = type_hash_canon (hashcode, t);  if (TYPE_SIZE (t) == 0)    layout_type (t);  return t;}treebuild_cplus_staticfn_type (basetype, rettype, argtypes)     tree basetype, rettype, argtypes;{  register tree t;  int hashcode;  /* Make a node of the sort we want.  */  t = make_node (FUNCTION_TYPE);  TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);  TREE_TYPE (t) = rettype;  TYPE_ARG_TYPES (t) = argtypes;  /* If we already have such a type, use the old one and free this one.     Note that it also frees up the above cons cell if found.  */  hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);  t = type_hash_canon (hashcode, t);  if (TYPE_SIZE (t) == 0)    layout_type (t);  return t;}treebuild_cplus_array_type (elt_type, index_type)     tree elt_type;     tree index_type;{  register struct obstack *ambient_obstack = current_obstack;  register struct obstack *ambient_saveable_obstack = saveable_obstack;  tree t;  /* We need a new one.  If both ELT_TYPE and INDEX_TYPE are permanent,     make this permanent too.  */  if (TREE_PERMANENT (elt_type)      && (index_type == 0 || TREE_PERMANENT (index_type)))    {      current_obstack = &permanent_obstack;      saveable_obstack = &permanent_obstack;    }  t = build_array_type (elt_type, index_type);  /* Push these needs up so that initialization takes place     more easily.  */  TYPE_NEEDS_CONSTRUCTING (t) = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));  TYPE_NEEDS_DESTRUCTOR (t) = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));  current_obstack = ambient_obstack;  saveable_obstack = ambient_saveable_obstack;  return t;}/* Make a variant type in the proper way for C/C++, propagating qualifiers   down to the element type of an array.  */treecp_build_type_variant (type, constp, volatilep)     tree type;     int constp, volatilep;{  if (TREE_CODE (type) == ARRAY_TYPE)    {      tree real_main_variant = TYPE_MAIN_VARIANT (type);      push_obstacks (TYPE_OBSTACK (real_main_variant),		     TYPE_OBSTACK (real_main_variant));      type = build_cplus_array_type (cp_build_type_variant (TREE_TYPE (type),							    constp, volatilep),				     TYPE_DOMAIN (type));      /* TYPE must be on same obstack as REAL_MAIN_VARIANT.  If not,	 make a copy.  (TYPE might have come from the hash table and	 REAL_MAIN_VARIANT might be in some function's obstack.)  */      if (TYPE_OBSTACK (type) != TYPE_OBSTACK (real_main_variant))	{

⌨️ 快捷键说明

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