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

📄 typeck.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
     tree exp;{  tree type;  enum tree_code code;  exp = decay_conversion (exp);  type = TREE_TYPE (exp);  code = TREE_CODE (type);  if (INTEGRAL_CODE_P (code))    {      tree t = type_promotes_to (type);      if (t != type)	return cp_convert (t, exp);    }  return exp;}/* Take the address of an inline function without setting TREE_ADDRESSABLE   or TREE_USED.  */treeinline_conversion (exp)     tree exp;{  if (TREE_CODE (exp) == FUNCTION_DECL)    exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);  return exp;}/* Returns nonzero iff exp is a STRING_CST or the result of applying   decay_conversion to one.  */intstring_conv_p (totype, exp, warn)     tree totype, exp;     int warn;{  tree t;  if (! flag_const_strings || TREE_CODE (totype) != POINTER_TYPE)    return 0;  t = TREE_TYPE (totype);  if (!same_type_p (t, char_type_node)      && !same_type_p (t, wchar_type_node))    return 0;  if (TREE_CODE (exp) == STRING_CST)    {      /* Make sure that we don't try to convert between char and wchar_t.  */      if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), t))	return 0;    }  else    {      /* Is this a string constant which has decayed to 'const char *'?  */      t = build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));      if (!same_type_p (TREE_TYPE (exp), t))	return 0;      STRIP_NOPS (exp);      if (TREE_CODE (exp) != ADDR_EXPR	  || TREE_CODE (TREE_OPERAND (exp, 0)) != STRING_CST)	return 0;    }  /* This warning is not very useful, as it complains about printf.  */  if (warn && warn_write_strings)    cp_warning ("deprecated conversion from string constant to `%T'", totype);  return 1;}treebuild_object_ref (datum, basetype, field)     tree datum, basetype, field;{  tree dtype;  if (datum == error_mark_node)    return error_mark_node;  dtype = TREE_TYPE (datum);  if (TREE_CODE (dtype) == REFERENCE_TYPE)    dtype = TREE_TYPE (dtype);  if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype)))    {      cp_error ("request for member `%T::%D' in expression of non-aggregate type `%T'",		basetype, field, dtype);      return error_mark_node;    }  else if (IS_SIGNATURE (basetype))    {      warning ("signature name in scope resolution ignored");      return build_component_ref (datum, field, NULL_TREE, 1);    }  else if (is_aggr_type (basetype, 1))    {      tree binfo = binfo_or_else (basetype, dtype);      if (binfo)	return build_x_component_ref (build_scoped_ref (datum, basetype),				      field, binfo, 1);    }  return error_mark_node;}/* Like `build_component_ref, but uses an already found field, and converts   from a reference.  Must compute access for current_class_ref.   Otherwise, ok.  */treebuild_component_ref_1 (datum, field, protect)     tree datum, field;     int protect;{  return convert_from_reference    (build_component_ref (datum, field, NULL_TREE, protect));}/* Given a COND_EXPR, MIN_EXPR, or MAX_EXPR in T, return it in a form that we   can, for example, use as an lvalue.  This code used to be in   unary_complex_lvalue, but we needed it to deal with `a = (d == c) ? b : c'   expressions, where we're dealing with aggregates.  But now it's again only   called from unary_complex_lvalue.  The case (in particular) that led to   this was with CODE == ADDR_EXPR, since it's not an lvalue when we'd   get it there.  */static treerationalize_conditional_expr (code, t)     enum tree_code code;     tree t;{  /* For MIN_EXPR or MAX_EXPR, fold-const.c has arranged things so that     the first operand is always the one to be used if both operands     are equal, so we know what conditional expression this used to be.  */  if (TREE_CODE (t) == MIN_EXPR || TREE_CODE (t) == MAX_EXPR)    {      return	build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR						    ? LE_EXPR : GE_EXPR),						   TREE_OPERAND (t, 0),						   TREE_OPERAND (t, 1)),			    build_unary_op (code, TREE_OPERAND (t, 0), 0),			    build_unary_op (code, TREE_OPERAND (t, 1), 0));    }  return    build_conditional_expr (TREE_OPERAND (t, 0),			    build_unary_op (code, TREE_OPERAND (t, 1), 0),			    build_unary_op (code, TREE_OPERAND (t, 2), 0));}/* Given the TYPE of an anonymous union field inside T, return the   FIELD_DECL for the field.  If not found return NULL_TREE.  Because   anonymous unions can nest, we must also search all anonymous unions   that are directly reachable.  */static treelookup_anon_field (t, type)     tree t, type;{  tree field;  for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))    {      if (TREE_STATIC (field))	continue;      if (TREE_CODE (field) != FIELD_DECL)	continue;      /* If we find it directly, return the field.  */      if (DECL_NAME (field) == NULL_TREE	  && type == TREE_TYPE (field))	{	  return field;	}      /* Otherwise, it could be nested, search harder.  */      if (DECL_NAME (field) == NULL_TREE	  && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)	{	  tree subfield = lookup_anon_field (TREE_TYPE (field), type);	  if (subfield)	    return subfield;	}    }  return NULL_TREE;}/* Build a COMPONENT_REF for a given DATUM, and it's member COMPONENT.   COMPONENT can be an IDENTIFIER_NODE that is the name of the member   that we are interested in, or it can be a FIELD_DECL.  */treebuild_component_ref (datum, component, basetype_path, protect)     tree datum, component, basetype_path;     int protect;{  register tree basetype;  register enum tree_code code;  register tree field = NULL;  register tree ref;  tree field_type;  int type_quals;  if (processing_template_decl)    return build_min_nt (COMPONENT_REF, datum, component);    if (datum == error_mark_node       || TREE_TYPE (datum) == error_mark_node)    return error_mark_node;  /* BASETYPE holds the type of the class containing the COMPONENT.  */  basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));      /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference     inside it.  */  switch (TREE_CODE (datum))    {    case COMPOUND_EXPR:      {	tree value = build_component_ref (TREE_OPERAND (datum, 1), component,					  basetype_path, protect);	return build (COMPOUND_EXPR, TREE_TYPE (value),		      TREE_OPERAND (datum, 0), value);      }    case COND_EXPR:      return build_conditional_expr	(TREE_OPERAND (datum, 0),	 build_component_ref (TREE_OPERAND (datum, 1), component,			      basetype_path, protect),	 build_component_ref (TREE_OPERAND (datum, 2), component,			      basetype_path, protect));    case TEMPLATE_DECL:      cp_error ("invalid use of %D", datum);      datum = error_mark_node;      break;    default:      break;    }  code = TREE_CODE (basetype);  if (code == REFERENCE_TYPE)    {      datum = convert_from_reference (datum);      basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));      code = TREE_CODE (basetype);    }  if (TREE_CODE (datum) == OFFSET_REF)    {      datum = resolve_offset_ref (datum);      basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));      code = TREE_CODE (basetype);    }  /* First, see if there is a field or component with name COMPONENT.  */  if (TREE_CODE (component) == TREE_LIST)    {      /* I could not trigger this code. MvL */      my_friendly_abort (980326);#ifdef DEAD      my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE		&& DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);#endif      return build (COMPONENT_REF, TREE_TYPE (component), datum, component);    }  if (! IS_AGGR_TYPE_CODE (code))    {      if (code != ERROR_MARK)	cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",		  component, datum, basetype);      return error_mark_node;    }  if (!complete_type_or_else (basetype, datum))    return error_mark_node;  if (TREE_CODE (component) == BIT_NOT_EXPR)    {      if (TYPE_IDENTIFIER (basetype) != TREE_OPERAND (component, 0))	{	  cp_error ("destructor specifier `%T::~%T' must have matching names",		    basetype, TREE_OPERAND (component, 0));	  return error_mark_node;	}      if (! TYPE_HAS_DESTRUCTOR (basetype))	{	  cp_error ("type `%T' has no destructor", basetype);	  return error_mark_node;	}      return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1);    }  /* Look up component name in the structure type definition.  */  if (CLASSTYPE_VFIELD (basetype)      && DECL_NAME (CLASSTYPE_VFIELD (basetype)) == component)    /* Special-case this because if we use normal lookups in an ambiguous       hierarchy, the compiler will abort (because vptr lookups are       not supposed to be ambiguous.  */    field = CLASSTYPE_VFIELD (basetype);  else if (TREE_CODE (component) == FIELD_DECL)    field = component;  else if (TREE_CODE (component) == TYPE_DECL)    {      cp_error ("invalid use of type decl `%#D' as expression", component);      return error_mark_node;    }  else    {      tree name = component;      if (TREE_CODE (component) == VAR_DECL)	name = DECL_NAME (component);      if (basetype_path == NULL_TREE)	basetype_path = TYPE_BINFO (basetype);      field = lookup_field (basetype_path, name,			    protect && !VFIELD_NAME_P (name), 0);      if (field == error_mark_node)	return error_mark_node;      if (field == NULL_TREE)	{	  /* Not found as a data field, look for it as a method.  If found,	     then if this is the only possible one, return it, else	     report ambiguity error.  */	  tree fndecls = lookup_fnfields (basetype_path, name, 1);	  if (fndecls == error_mark_node)	    return error_mark_node;	  if (fndecls)	    {	      /* If the function is unique and static, we can resolve it		 now.  Otherwise, we have to wait and see what context it is		 used in; a component_ref involving a non-static member		 function can only be used in a call (expr.ref).  */	      if (TREE_CHAIN (fndecls) == NULL_TREE		  && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL)		{		  if (DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))		    {		      tree fndecl = TREE_VALUE (fndecls);		      enforce_access (TREE_PURPOSE (fndecls), fndecl);		      mark_used (fndecl);		      return fndecl;		    }		  else		    {		      /* A unique non-static member function.  Other parts			 of the compiler expect something with			 unknown_type_node to be really overloaded, so			 let's oblige.  */		      TREE_VALUE (fndecls)			= scratch_ovl_cons (TREE_VALUE (fndecls), NULL_TREE);		    }		}	      ref = build (COMPONENT_REF, unknown_type_node,			   datum, TREE_VALUE (fndecls));	      return ref;	    }	  cp_error ("`%#T' has no member named `%D'", basetype, name);	  return error_mark_node;	}      else if (TREE_TYPE (field) == error_mark_node)	return error_mark_node;      if (TREE_CODE (field) != FIELD_DECL)	{	  if (TREE_CODE (field) == TYPE_DECL)	    cp_pedwarn ("invalid use of type decl `%#D' as expression", field);	  else if (DECL_RTL (field) != 0)	    mark_used (field);	  else	    TREE_USED (field) = 1;	  return field;	}    }  /* See if we have to do any conversions so that we pick up the field from the     right context.  */  if (DECL_FIELD_CONTEXT (field) != basetype)    {      tree context = DECL_FIELD_CONTEXT (field);      tree base = context;      while (!same_type_p (base, basetype) && TYPE_NAME (base)	     && ANON_UNION_TYPE_P (base))	{	  base = TYPE_CONTEXT (base);	}      /* Handle base classes here...  */      if (base != basetype && TYPE_USES_COMPLEX_INHERITANCE (basetype))	{	  tree addr = build_unary_op (ADDR_EXPR, datum, 0);	  if (integer_zerop (addr))	    {	      error ("invalid reference to NULL ptr, use ptr-to-member instead");	      return error_mark_node;	    }	  if (VBASE_NAME_P (DECL_NAME (field)))	    {	      /* It doesn't matter which vbase pointer we grab, just		 find one of them.  */	      tree binfo = get_binfo (base,				      TREE_TYPE (TREE_TYPE (addr)), 0);	      addr = convert_pointer_to_real (binfo, addr);	    }	  else	    addr = convert_pointer_to (base, addr);	  datum = build_indirect_ref (addr, NULL_PTR);	  my_friendly_assert (datum != error_mark_node, 311);	}      basetype = base;       /* Handle things from anon unions here...  */      if (TYPE_NAME (context) && ANON_UNION_TYPE_P (context))	{	  tree subfield = lookup_anon_field (basetype, context);	  tree subdatum = build_component_ref (datum, subfield,					       basetype_path, protect);	  return build_component_ref (subdatum, field, basetype_path, protect);	}    }  /* Compute the type of the field, as described in [expr.ref].  */  type_quals = TYPE_UNQUALIFIED;  field_type = TREE_TYPE (field);  if (TREE_CODE (field_type) == REFERENCE_TYPE)    /* The standard says that the type of the result should be the       type referred to by the reference.  But for now, at least, we       do the conversion from reference type later.  */    ;  else    {      type_quals = (CP_TYPE_QUALS (field_type)  		    | CP_TYPE_QUALS (TREE_TYPE (datum)));      /* A field is const (volatile) if the enclosing object, or the	 field itself, is const (volatile).  But, a mutable field is	 not const, even within a const object.  */      if (DECL_LANG_SPECIFIC (field) && DECL_MUTABLE_P (field))	type_quals &= ~TYPE_QUAL_CONST;      if (!IS_SIGNATURE (field_type))	field_type = cp_build_qualified_type (field_type, type_quals);    }  ref = fold (build (COMPONENT_REF, field_type,		     break_out_cleanups (datum), field));  /* Mark the expression const or volatile, as appropriate.  Even     though we've dealt with the type above, we still have to mark the     expression itse

⌨️ 快捷键说明

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