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

📄 cp-type2.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
   to be called.   If INIT is a TREE_LIST and there is no constructor, turn INIT   into a CONSTRUCTOR and use standard initialization techniques.   Perhaps a warning should be generated?   Returns value of initializer if initialization could not be   performed for static variable.  In that case, caller must do   the storing.  */treestore_init_value (decl, init)     tree decl, init;{  register tree value, type;  /* If variable's type was invalidly declared, just ignore it.  */  type = TREE_TYPE (decl);  if (TREE_CODE (type) == ERROR_MARK)    return NULL_TREE;  /* Take care of C++ business up here.  */  type = TYPE_MAIN_VARIANT (type);  /* implicitly tests if IS_AGGR_TYPE.  */  if (TYPE_NEEDS_CONSTRUCTING (type))    my_friendly_abort (109);  else if (IS_AGGR_TYPE (type))    {      /* @@ This may be wrong, but I do not know what is right.  */      if (TREE_CODE (init) == TREE_LIST)	{	  error_with_aggr_type (type, "constructor syntax used, but no constructor declared for type `%s'");	  init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));	}    }  else if (TREE_CODE (init) == TREE_LIST	   && TREE_TYPE (init) != unknown_type_node)    {      if (TREE_CODE (decl) == RESULT_DECL)	{	  if (TREE_CHAIN (init))	    {	      warning ("comma expression used to initialize return value");	      init = build_compound_expr (init);	    }	  else	    init = TREE_VALUE (init);	}      else if (TREE_TYPE (init) != 0	       && TREE_CODE (TREE_TYPE (init)) == OFFSET_TYPE)	{	  /* Use the type of our variable to instantiate	     the type of our initializer.  */	  init = instantiate_type (type, init, 1);	}      else if (TREE_CODE (init) == TREE_LIST	       && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)	{	  error ("cannot initialize arrays using this syntax");	  return NULL_TREE;	}      else	{	  error ("bad syntax in initialization");	  return NULL_TREE;	}    }  /* End of special C++ code.  */  /* Digest the specified initializer into an expression.  */  value = digest_init (type, init, 0);  /* Store the expression if valid; else report error.  */  if (TREE_CODE (value) == ERROR_MARK)    ;  else if (TREE_STATIC (decl)	   && (! TREE_CONSTANT (value)	       || ! initializer_constant_valid_p (value)	       /* Since ctors and dtors are the only things that can		  reference vtables, and they are always written down		  the the vtable definition, we can leave the		  vtables in initialized data space.		  However, other initialized data cannot be initialized		  this way.  Instead a global file-level initializer		  must do the job.  */	       || (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))))    return value;  else    {      if (pedantic && TREE_CODE (value) == CONSTRUCTOR)	{	  if (! TREE_CONSTANT (value) || ! TREE_STATIC (value))	    pedwarn ("ANSI C++ forbids non-constant aggregate initializer expressions");	}    }  DECL_INITIAL (decl) = value;  return NULL_TREE;}/* Digest the parser output INIT as an initializer for type TYPE.   Return a C expression of type TYPE to represent the initial value.   If TAIL is nonzero, it points to a variable holding a list of elements   of which INIT is the first.  We update the list stored there by   removing from the head all the elements that we use.   Normally this is only one; we use more than one element only if   TYPE is an aggregate and INIT is not a constructor.  */treedigest_init (type, init, tail)     tree type, init, *tail;{  enum tree_code code = TREE_CODE (type);  tree element = 0;  tree old_tail_contents;  /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR     tree node which has no TREE_TYPE.  */  int raw_constructor    = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;  /* By default, assume we use one element from a list.     We correct this later in the sole case where it is not true.  */  if (tail)    {      old_tail_contents = *tail;      *tail = TREE_CHAIN (*tail);    }  if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST				  && TREE_VALUE (init) == error_mark_node))    return error_mark_node;  /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */  if (TREE_CODE (init) == NON_LVALUE_EXPR)    init = TREE_OPERAND (init, 0);  if (init && raw_constructor      && CONSTRUCTOR_ELTS (init) != 0      && TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0)    {      element = TREE_VALUE (CONSTRUCTOR_ELTS (init));      /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */      if (element && TREE_CODE (element) == NON_LVALUE_EXPR)	element = TREE_OPERAND (element, 0);      if (element == error_mark_node)	return element;    }  /* Any type can be initialized from an expression of the same type,     optionally with braces.  */  if (init && TREE_TYPE (init)      && (TYPE_MAIN_VARIANT (TREE_TYPE (init)) == type	  || (code == ARRAY_TYPE && comptypes (TREE_TYPE (init), type, 1))))    {      if (pedantic && code == ARRAY_TYPE	  && TREE_CODE (init) != STRING_CST)	pedwarn ("ANSI C++ forbids initializing array from array expression");      if (TREE_CODE (init) == CONST_DECL)	init = DECL_INITIAL (init);      else if (TREE_READONLY_DECL_P (init))	init = decl_constant_value (init);      return init;    }  if (element && (TREE_TYPE (element) == type		  || (code == ARRAY_TYPE && TREE_TYPE (element)		      && comptypes (TREE_TYPE (element), type, 1))))    {      if (pedantic && code == ARRAY_TYPE)	pedwarn ("ANSI C++ forbids initializing array from array expression");      if (pedantic && (code == RECORD_TYPE || code == UNION_TYPE))	pedwarn ("ANSI C++ forbids single nonscalar initializer with braces");      if (TREE_CODE (element) == CONST_DECL)	element = DECL_INITIAL (element);      else if (TREE_READONLY_DECL_P (element))	element = decl_constant_value (element);      return element;    }  /* Check for initializing a union by its first field.     Such an initializer must use braces.  */  if (code == UNION_TYPE)    {      tree result, field = TYPE_FIELDS (type);      /* Find the first named field.  ANSI decided in September 1990	 that only named fields count here.  */      while (field && DECL_NAME (field) == 0)	field = TREE_CHAIN (field);      if (field == 0)	{	  error ("union with no named members cannot be initialized");	  return error_mark_node;	}      if (! raw_constructor)	{	  error ("type mismatch in initialization");	  return error_mark_node;	}      if (element == 0)	{	  if (!TYPE_NEEDS_CONSTRUCTING (type))	    {	      error ("union initializer requires one element");	      return error_mark_node;	    }	}      else	{	  /* Take just the first element from within the constructor	     and it should match the type of the first element.  */	  element = digest_init (TREE_TYPE (field), element, 0);	  result = build (CONSTRUCTOR, type, 0, build_tree_list (field, element));	  TREE_CONSTANT (result) = TREE_CONSTANT (element);	  TREE_STATIC (result) = (initializer_constant_valid_p (element)				  && TREE_CONSTANT (element));	  return result;	}    }  /* Initialization of an array of chars from a string constant     optionally enclosed in braces.  */  if (code == ARRAY_TYPE)    {      tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));      if ((typ1 == char_type_node	   || typ1 == signed_char_type_node	   || typ1 == unsigned_char_type_node	   || typ1 == unsigned_wchar_type_node	   || typ1 == signed_wchar_type_node)	  && ((init && TREE_CODE (init) == STRING_CST)	      || (element && TREE_CODE (element) == STRING_CST)))	{	  tree string = element ? element : init;	  if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))	       != char_type_node)	      && TYPE_PRECISION (typ1) == BITS_PER_UNIT)	    {	      error ("char-array initialized from wide string");	      return error_mark_node;	    }	  if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))	       == char_type_node)	      && TYPE_PRECISION (typ1) != BITS_PER_UNIT)	    {	      error ("int-array initialized from non-wide string");	      return error_mark_node;	    }	  if (pedantic && typ1 != char_type_node)	    pedwarn ("ANSI C++ forbids string initializer except for `char' elements");	  TREE_TYPE (string) = type;	  if (TYPE_DOMAIN (type) != 0	      && TREE_CONSTANT (TYPE_SIZE (type)))	    {	      register int size		= TREE_INT_CST_LOW (TYPE_SIZE (type));	      size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;	      /* In C it is ok to subtract 1 from the length of the string		 because it's ok to ignore the terminating null char that is		 counted in the length of the constant, but in C++ this would		 be invalid.  */	      if (size < TREE_STRING_LENGTH (string))		warning ("initializer-string for array of chars is too long");	    }	  return string;	}    }  /* Handle scalar types, including conversions.  */  if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE      || code == ENUMERAL_TYPE || code == REFERENCE_TYPE)    {      if (raw_constructor)	{	  if (element == 0)	    {	      error ("initializer for scalar variable requires one element");	      return error_mark_node;	    }	  init = element;	}      return convert_for_initialization (0, type, init, LOOKUP_NORMAL,					 "initialization", NULL_TREE, 0);    }  /* Come here only for records and arrays (and unions with constructors).  */  if (TYPE_SIZE (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))    {      error ("variable-sized object may not be initialized");      return error_mark_node;    }  if (code == ARRAY_TYPE || code == RECORD_TYPE || code == UNION_TYPE)    {      if (raw_constructor)	return process_init_constructor (type, init, 0);      else if (TYPE_NEEDS_CONSTRUCTING (type))	{	  /* This can only be reached when caller is initializing	     ARRAY_TYPE.  In that case, we don't want to convert	     INIT to TYPE.  We will let `expand_vec_init' do it.  */	  return init;	}      else if (tail != 0)	{	  *tail = old_tail_contents;	  return process_init_constructor (type, 0, tail);	}      else if (flag_traditional)	/* Traditionally one can say `char x[100] = 0;'.  */	return process_init_constructor (type,					 build_nt (CONSTRUCTOR, 0,						   tree_cons (0, init, 0)),					 0);      if (code != ARRAY_TYPE)	return convert_for_initialization (0, type, init, LOOKUP_NORMAL,					   "initialization", NULL_TREE, 0);    }  error ("invalid initializer");  return error_mark_node;}/* Process a constructor for a variable of type TYPE.   The constructor elements may be specified either with INIT or with ELTS,   only one of which should be non-null.   If INIT is specified, it is a CONSTRUCTOR node which is specifically   and solely for initializing this datum.   If ELTS is specified, it is the address of a variable containing   a list of expressions.  We take as many elements as we need   from the head of the list and update the list.   In the resulting constructor, TREE_CONSTANT is set if all elts are   constant, and TREE_STATIC is set if, in addition, all elts are simple enough   constants that the assembler and linker can compute them.  */static treeprocess_init_constructor (type, init, elts)     tree type, init, *elts;{  extern tree empty_init_node;  register tree tail;  /* List of the elements of the result constructor,     in reverse order.  */  register tree members = NULL;  tree result;  int allconstant = 1;  int allsimple = 1;  int erred = 0;  /* Make TAIL be the list of elements to use for the initialization,     no matter how the data was given to us.  */  if (elts)    {      if (extra_warnings)	warning ("aggregate has a partly bracketed initializer");      tail = *elts;    }  else    tail = CONSTRUCTOR_ELTS (init);  /* Gobble as many elements as needed, and make a constructor or initial value     for each element of this aggregate.  Chain them together in result.     If there are too few, use 0 for each scalar ultimate component.  */  if (TREE_CODE (type) == ARRAY_TYPE)    {      tree domain = TYPE_DOMAIN (type);      register long len;      register int i;      if (domain)	len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain))

⌨️ 快捷键说明

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