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

📄 cp-cvt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Language-level data type conversion for GNU C++.   Copyright (C) 1987, 1988, 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 contains the functions for converting C expressions   to different data types.  The only entry point is `convert'.   Every language front end must have a `convert' function   but what kind of conversions it does will depend on the language.  */#include "config.h"#include "tree.h"#include "flags.h"#include "cp-tree.h"#include "cp-class.h"#define NULL 0extern void warn_for_assignment ();/* Change of width--truncation and extension of integers or reals--   is represented with NOP_EXPR.  Proper functioning of many things   assumes that no other conversions can be NOP_EXPRs.   Conversion between integer and pointer is represented with CONVERT_EXPR.   Converting integer to real uses FLOAT_EXPR   and real to integer uses FIX_TRUNC_EXPR.   Here is a list of all the functions that assume that widening and   narrowing is always done with a NOP_EXPR:     In c-convert.c, convert_to_integer.     In c-typeck.c, build_binary_op_nodefault (boolean ops),        and truthvalue_conversion.     In expr.c: expand_expr, for operands of a MULT_EXPR.     In fold-const.c: fold.     In tree.c: get_narrower and get_unwidened.   C++: in multiple-inheritance, converting between pointers may involve   adjusting them by a delta stored within the class definition.  *//* Subroutines of `convert'.  */static treeconvert_to_pointer (type, expr)     tree type, expr;{  register tree intype = TREE_TYPE (expr);  register enum tree_code form = TREE_CODE (intype);    if (integer_zerop (expr))    {      if (type == TREE_TYPE (null_pointer_node))	return null_pointer_node;      expr = build_int_2 (0, 0);      TREE_TYPE (expr) = type;      return expr;    }  if (form == POINTER_TYPE)    {      intype = TYPE_MAIN_VARIANT (intype);      if (TYPE_MAIN_VARIANT (type) != intype	  && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE	  && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)	{	  enum tree_code code = PLUS_EXPR;	  tree binfo = get_binfo (TREE_TYPE (type), TREE_TYPE (intype), 1);	  if (binfo == error_mark_node)	    return error_mark_node;	  if (binfo == NULL_TREE)	    {	      binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 1);	      if (binfo == error_mark_node)		return error_mark_node;	      code = MINUS_EXPR;	    }	  if (binfo)	    {	      if (TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (type))		  || TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (intype))		  || ! BINFO_OFFSET_ZEROP (binfo))		{		  /* Need to get the path we took.  */		  tree path;		  if (code == PLUS_EXPR)		    get_base_distance (TREE_TYPE (type), TREE_TYPE (intype), 0, &path);		  else		    get_base_distance (TREE_TYPE (intype), TREE_TYPE (type), 0, &path);		  return build_vbase_path (code, type, expr, path, 0);		}	    }	}      return build1 (NOP_EXPR, type, expr);    }  if (form == INTEGER_TYPE || form == ENUMERAL_TYPE)    {      if (type_precision (intype) == POINTER_SIZE)	return build1 (CONVERT_EXPR, type, expr);      return convert_to_pointer (type,				 convert (type_for_size (POINTER_SIZE, 0),					  expr));    }  my_friendly_assert (form != OFFSET_TYPE, 186);  if (IS_AGGR_TYPE (intype))    {      /* If we cannot convert to the specific pointer type,	 try to convert to the type `void *'.  */      tree rval;      rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);      if (rval)	{	  if (rval == error_mark_node)	    error ("ambiguous pointer conversion");	  return rval;	}    }  error ("cannot convert to a pointer type");  return null_pointer_node;}/* Like convert, except permit conversions to take place which   are not normally allowed due to visibility restrictions   (such as conversion from sub-type to private super-type).  */static treeconvert_to_pointer_force (type, expr)     tree type, expr;{  register tree intype = TREE_TYPE (expr);  register enum tree_code form = TREE_CODE (intype);    if (integer_zerop (expr))    {      if (type == TREE_TYPE (null_pointer_node))	return null_pointer_node;      expr = build_int_2 (0, 0);      TREE_TYPE (expr) = type;      return expr;    }  if (form == POINTER_TYPE)    {      intype = TYPE_MAIN_VARIANT (intype);      if (TYPE_MAIN_VARIANT (type) != intype	  && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE	  && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)	{	  enum tree_code code = PLUS_EXPR;	  tree path;	  int distance = get_base_distance (TREE_TYPE (type),					    TREE_TYPE (intype), 0, &path);	  if (distance == -2)	    {	    ambig:	      error_with_aggr_type (TREE_TYPE (type), "type `%s' is ambiguous baseclass of `%s'",				    TYPE_NAME_STRING (TREE_TYPE (intype)));	      return error_mark_node;	    }	  if (distance == -1)	    {	      distance = get_base_distance (TREE_TYPE (intype),					    TREE_TYPE (type), 0, &path);	      if (distance == -2)		goto ambig;	      if (distance < 0)		/* Doesn't need any special help from us.  */		return build1 (NOP_EXPR, type, expr);	      code = MINUS_EXPR;	    }	  return build_vbase_path (code, type, expr, path, 0);	}      return build1 (NOP_EXPR, type, expr);    }  return convert_to_pointer (type, expr);}/* We are passing something to a function which requires a reference.   The type we are interested in is in TYPE. The initial   value we have to begin with is in ARG.   FLAGS controls how we manage visibility checking.   CHECKCONST controls if we report error messages on const subversion.  */static treebuild_up_reference (type, arg, flags, checkconst)     tree type, arg;     int flags, checkconst;{  tree rval, targ;  int literal_flag = 0;  tree argtype = TREE_TYPE (arg), basetype = argtype;  tree target_type = TREE_TYPE (type);  tree binfo = NULL_TREE;  my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);  if (flags != 0      && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)      && IS_AGGR_TYPE (argtype)      && IS_AGGR_TYPE (target_type))    {      binfo = get_binfo (target_type, argtype,			      (flags & LOOKUP_PROTECTED_OK) ? 3 : 2);      if ((flags & LOOKUP_PROTECT) && binfo == error_mark_node)	return error_mark_node;      if (basetype == NULL_TREE)	return error_not_base_type (target_type, argtype);      basetype = BINFO_TYPE (binfo);    }  /* Pass along const and volatile down into the type. */  if (TYPE_READONLY (type) || TYPE_VOLATILE (type))    target_type = build_type_variant (target_type, TYPE_READONLY (type),				      TYPE_VOLATILE (type));  targ = arg;  if (TREE_CODE (targ) == SAVE_EXPR)    targ = TREE_OPERAND (targ, 0);  switch (TREE_CODE (targ))    {    case INDIRECT_REF:      /* This is a call to a constructor which did not know what it was	 initializing until now: it needs to initialize a temporary.  */      if (TREE_HAS_CONSTRUCTOR (targ))	{	  tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0), 1);	  TREE_HAS_CONSTRUCTOR (targ) = 0;	  return build_up_reference (type, temp, flags, 1);	}      /* Let &* cancel out to simplify resulting code.         Also, throw away intervening NOP_EXPRs.  */      arg = TREE_OPERAND (targ, 0);      if (TREE_CODE (arg) == NOP_EXPR || TREE_CODE (arg) == NON_LVALUE_EXPR	  || (TREE_CODE (arg) == CONVERT_EXPR && TREE_REFERENCE_EXPR (arg)))	arg = TREE_OPERAND (arg, 0);      /* in doing a &*, we have to get rid of the const'ness on the pointer	 value.  Haven't thought about volatile here.  Pointers come to mind	 here.  */      if (TREE_READONLY (arg))	{	  arg = copy_node (arg);	  TREE_READONLY (arg) = 0;	}      rval = build1 (CONVERT_EXPR, type, arg);      TREE_REFERENCE_EXPR (rval) = 1;      /* propagate the const flag on something like:	 class Base {	 public:	   int foo;	 };      class Derived : public Base {      public:	int bar;      };      void func(Base&);      void func2(const Derived& d) {	func(d);      }        on the d parameter.  The below could have been avoided, if the flags        were down in the tree, not sure why they are not.  (mrs) */      /* The below code may have to be propagated to other parts of this	 switch.  */      if (TREE_READONLY (targ) && !TREE_READONLY (arg)	  && (TREE_CODE (arg) == PARM_DECL || TREE_CODE (arg) == VAR_DECL)	  && TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE	  && (TYPE_READONLY (target_type) && checkconst))	{	  arg = copy_node (arg);	  TREE_READONLY (arg) = TREE_READONLY (targ);	}      literal_flag = TREE_CONSTANT (arg);      goto done_but_maybe_warn;      /* Get this out of a register if we happened to be in one by accident.	 Also, build up references to non-lvalues it we must.  */      /* For &x[y], return (&) x+y */    case ARRAY_REF:      if (mark_addressable (TREE_OPERAND (targ, 0)) == 0)	return error_mark_node;      rval = build_binary_op (PLUS_EXPR, TREE_OPERAND (targ, 0),			      TREE_OPERAND (targ, 1));      TREE_TYPE (rval) = type;      if (TREE_CONSTANT (TREE_OPERAND (targ, 1))	  && staticp (TREE_OPERAND (targ, 0)))	TREE_CONSTANT (rval) = 1;      goto done;    case SCOPE_REF:      /* Could be a reference to a static member.  */      {	tree field = TREE_OPERAND (targ, 1);	if (TREE_STATIC (field))	  {	    rval = build1 (ADDR_EXPR, type, field);	    literal_flag = 1;	    goto done;	  }      }      /* we should have farmed out member pointers above.  */      my_friendly_assert (0, 188);    case COMPONENT_REF:      rval = build_component_addr (targ, build_pointer_type (argtype),				   "attempt to make a reference to bit-field structure member `%s'");      TREE_TYPE (rval) = type;      literal_flag = staticp (TREE_OPERAND (targ, 0));      goto done_but_maybe_warn;      /* Anything not already handled and not a true memory reference	 needs to have a reference built up.  Do so silently for	 things like integers and return values from function,	 but complain if we need a reference to something declared	 as `register'.  */    case RESULT_DECL:      if (staticp (targ))	literal_flag = 1;      TREE_ADDRESSABLE (targ) = 1;      put_var_into_stack (targ);      break;    case PARM_DECL:      if (targ == current_class_decl)	{	  error ("address of `this' not available");#if 0	  /* This code makes the following core dump the compiler on a sun4,	     if the code below is used.	     class e_decl;	     class a_decl;	     typedef a_decl* a_ref;	     class a_s {	     public:	       a_s();	       void* append(a_ref& item);	     };	     class a_decl {	     public:	       a_decl (e_decl *parent);	       a_s  generic_s;	       a_s  decls;	       e_decl* parent;	     };	     class e_decl {	     public:	       e_decl();	       a_s implementations;	     };	     void foobar(void *);	     a_decl::a_decl(e_decl *parent) {	       parent->implementations.append(this);	     }	   */	  TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */	  put_var_into_stack (targ);#else	  return error_mark_node;#endif	  break;	}      /* Fall through.  */    case VAR_DECL:    case CONST_DECL:      if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ))	warning ("address needed to build reference for `%s', which is declared `register'",		 IDENTIFIER_POINTER (DECL_NAME (targ)));      else if (staticp (targ))	literal_flag = 1;      TREE_ADDRESSABLE (targ) = 1;      put_var_into_stack (targ);      break;    case COMPOUND_EXPR:      {	tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1),						  LOOKUP_PROTECT, checkconst);	rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference);	TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1));	return rval;      }    case MODIFY_EXPR:

⌨️ 快捷键说明

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