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

📄 tree.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Language-dependent node constructors for parse phase of GNU compiler.   Copyright (C) 1987, 88, 92-98, 1999 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 "system.h"#include "obstack.h"#include "tree.h"#include "cp-tree.h"#include "flags.h"#include "rtl.h"#include "toplev.h"static tree bot_manip PROTO((tree));static tree perm_manip PROTO((tree));static tree build_cplus_array_type_1 PROTO((tree, tree));static void list_hash_add PROTO((int, tree));static int list_hash PROTO((tree, tree, tree));static tree list_hash_lookup PROTO((int, tree, tree, tree));static void propagate_binfo_offsets PROTO((tree, tree));static int avoid_overlap PROTO((tree, tree));static int lvalue_p_1 PROTO((tree, int));static int equal_functions PROTO((tree, tree));static tree no_linkage_helper PROTO((tree));static tree build_srcloc PROTO((char *, int));#define CEIL(x,y) (((x) + (y) - 1) / (y))/* Returns non-zero if REF is an lvalue.  If   TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type   are considered lvalues.  */static intlvalue_p_1 (ref, treat_class_rvalues_as_lvalues)     tree ref;     int treat_class_rvalues_as_lvalues;{  if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)    return 1;  if (ref == current_class_ptr && 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:    case UNSAVE_EXPR:    case TRY_CATCH_EXPR:    case WITH_CLEANUP_EXPR:    case REALPART_EXPR:    case IMAGPART_EXPR:    case NOP_EXPR:      return lvalue_p_1 (TREE_OPERAND (ref, 0),			 treat_class_rvalues_as_lvalues);    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:      if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)	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_1 (TREE_OPERAND (ref, 0),			  treat_class_rvalues_as_lvalues)	      && lvalue_p_1 (TREE_OPERAND (ref, 1),			     treat_class_rvalues_as_lvalues));      break;    case COND_EXPR:      return (lvalue_p_1 (TREE_OPERAND (ref, 1),			  treat_class_rvalues_as_lvalues)	      && lvalue_p_1 (TREE_OPERAND (ref, 2),			     treat_class_rvalues_as_lvalues));    case MODIFY_EXPR:      return 1;    case COMPOUND_EXPR:      return lvalue_p_1 (TREE_OPERAND (ref, 1),			    treat_class_rvalues_as_lvalues);    case MAX_EXPR:    case MIN_EXPR:      return (lvalue_p_1 (TREE_OPERAND (ref, 0),			  treat_class_rvalues_as_lvalues)	      && lvalue_p_1 (TREE_OPERAND (ref, 1),			     treat_class_rvalues_as_lvalues));    case TARGET_EXPR:      return treat_class_rvalues_as_lvalues;    case CALL_EXPR:      return (treat_class_rvalues_as_lvalues	      && IS_AGGR_TYPE (TREE_TYPE (ref)));    case FUNCTION_DECL:      /* All functions (except non-static-member functions) are	 lvalues.  */      return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref);    default:      break;    }  return 0;}/* Return nonzero if REF is an lvalue valid for this language.   Lvalues can be assigned, unless they have TREE_READONLY, or unless   they are FUNCTION_DECLs.  Lvalues can have their address taken,   unless they have DECL_REGISTER.  */intreal_lvalue_p (ref)     tree ref;{  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);}/* This differs from real_lvalue_p in that class rvalues are considered   lvalues.  */intlvalue_p (ref)     tree ref;{  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1);}/* 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;     const 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.  */treebuild_cplus_new (type, init)     tree type;     tree init;{  tree slot;  tree rval;  if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)    return convert (type, init);  slot = build (VAR_DECL, type);  DECL_ARTIFICIAL (slot) = 1;  layout_decl (slot, 0);  rval = build (AGGR_INIT_EXPR, type,		TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);  TREE_SIDE_EFFECTS (rval) = 1;  rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE);  TREE_SIDE_EFFECTS (rval) = 1;  return rval;}/* Encapsulate the expression INIT in a TARGET_EXPR.  */treeget_target_expr (init)     tree init;{  tree slot;  tree rval;  slot = build (VAR_DECL, TREE_TYPE (init));  DECL_ARTIFICIAL (slot) = 1;  layout_decl (slot, 0);  rval = build (TARGET_EXPR, TREE_TYPE (init), slot, init,		NULL_TREE, NULL_TREE);  TREE_SIDE_EFFECTS (rval) = 1;  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);  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));	  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 = NULL_TREE;  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;extern struct obstack *expression_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 (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;}static treebuild_cplus_array_type_1 (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;    }  if (processing_template_decl       || uses_template_parms (elt_type)       || uses_template_parms (index_type))    {      t = make_node (ARRAY_TYPE);      TREE_TYPE (t) = elt_type;      TYPE_DOMAIN (t) = index_type;    }  else    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;}treebuild_cplus_array_type (elt_type, index_type)     tree elt_type;     tree index_type;{  tree t;  int type_quals = CP_TYPE_QUALS (elt_type);  elt_type = TYPE_MAIN_VARIANT (elt_type);  t = build_cplus_array_type_1 (elt_type, index_type);  if (type_quals != TYPE_UNQUALIFIED)    t = cp_build_qualified_type (t, type_quals);  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_qualified_type (type, type_quals)     tree type;     int type_quals;{  if (type == error_mark_node)    return type;    /* A restrict-qualified pointer type must be a pointer (or reference)     to object or incomplete type.  */  if ((type_quals & TYPE_QUAL_RESTRICT)      && (!POINTER_TYPE_P (type)	  || TYPE_PTRMEM_P (type)	  || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE))    {      cp_error ("`%T' cannot be `restrict'-qualified", type);      type_quals &= ~TYPE_QUAL_RESTRICT;    }  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_1 (cp_build_qualified_type 				       (TREE_TYPE (type), type_quals),				       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))	{	  type = copy_node (type);	  TYPE_POINTER_TO (type) = TYPE_REFERENCE_TO (type) = 0;	}      TYPE_MAIN_VARIANT (type) = real_main_variant;      pop_obstacks ();

⌨️ 快捷键说明

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