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

📄 typeck.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
#if 0	  if (component == ansi_opname[(int) TYPE_EXPR])	    cp_error ("`%#T' has no such type conversion operator", basetype);	  else#endif	    cp_error ("`%#T' has no member named `%D'", basetype, component);	  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_error ("invalid use of type decl `%#D' as expression", field);	      return error_mark_node;	    } 	  if (DECL_RTL (field) != 0)	    assemble_external (field);	  TREE_USED (field) = 1;	  return field;	}    }  if (DECL_FIELD_CONTEXT (field) != 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;	}      addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);      datum = build_indirect_ref (addr, NULL_PTR);      my_friendly_assert (datum != error_mark_node, 311);    }  ref = fold (build (COMPONENT_REF, TREE_TYPE (field),		     break_out_cleanups (datum), field));  if (TREE_READONLY (datum) || TREE_READONLY (field))    TREE_READONLY (ref) = 1;  if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))    TREE_THIS_VOLATILE (ref) = 1;  if (DECL_MUTABLE_P (field))    TREE_READONLY (ref) = 0;  return ref;}/* Given an expression PTR for a pointer, return an expression   for the value pointed to.   ERRORSTRING is the name of the operator to appear in error messages.   This function may need to overload OPERATOR_FNNAME.   Must also handle REFERENCE_TYPEs for C++.  */treebuild_x_indirect_ref (ptr, errorstring)     tree ptr;     char *errorstring;{  tree rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE);  if (rval)    return rval;  return build_indirect_ref (ptr, errorstring);}treebuild_indirect_ref (ptr, errorstring)     tree ptr;     char *errorstring;{  register tree pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE ?			   ptr : default_conversion (ptr));  register tree type = TREE_TYPE (pointer);  if (ptr == current_class_decl)    return C_C_D;  if (IS_AGGR_TYPE (type))    {      ptr = build_expr_type_conversion (WANT_POINTER, pointer, 1);      if (ptr)	{	  pointer = ptr;	  type = TREE_TYPE (pointer);	}    }  if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)    {      if (TREE_CODE (pointer) == ADDR_EXPR	  && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (pointer, 0)))	      == TYPE_MAIN_VARIANT (TREE_TYPE (type)))	  && (TREE_READONLY (TREE_OPERAND (pointer, 0))	      == TYPE_READONLY (TREE_TYPE (type)))	  && (TREE_THIS_VOLATILE (TREE_OPERAND (pointer, 0))	      == TYPE_VOLATILE (TREE_TYPE (type))))	return TREE_OPERAND (pointer, 0);      else	{	  tree t = TREE_TYPE (type);	  register tree ref = build1 (INDIRECT_REF,				      TYPE_MAIN_VARIANT (t), pointer);	  TREE_READONLY (ref) = TYPE_READONLY (t);	  TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);	  TREE_SIDE_EFFECTS (ref)	    = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);	  return ref;	}    }  /* `pointer' won't be an error_mark_node if we were given a     pointer to member, so it's cool to check for this here.  */  else if (TYPE_PTRMEMFUNC_P (type))    error ("invalid use of `%s' on pointer to member function", errorstring);  else if (TREE_CODE (type) == RECORD_TYPE	   && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))    error ("cannot dereference signature pointer/reference");  else if (pointer != error_mark_node)    {      if (errorstring)	error ("invalid type argument of `%s'", errorstring);      else	error ("invalid type argument");    }  return error_mark_node;}/* This handles expressions of the form "a[i]", which denotes   an array reference.   This is logically equivalent in C to *(a+i), but we may do it differently.   If A is a variable or a member, we generate a primitive ARRAY_REF.   This avoids forcing the array out of registers, and can work on   arrays that are not lvalues (for example, members of structures returned   by functions).   If INDEX is of some user-defined type, it must be converted to   integer type.  Otherwise, to make a compatible PLUS_EXPR, it   will inherit the type of the array, which will be some pointer type.  */treebuild_x_array_ref (array, index)     tree array, index;{  tree rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, index, NULL_TREE);  if (rval)    return rval;  return build_array_ref (array, index);}treebuild_array_ref (array, idx)     tree array, idx;{  tree itype;  if (idx == 0)    {      error ("subscript missing in array reference");      return error_mark_node;    }  if (TREE_TYPE (array) == error_mark_node      || TREE_TYPE (idx) == error_mark_node)    return error_mark_node;  itype = TREE_TYPE (idx);  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE      && TREE_CODE (array) != INDIRECT_REF)    {      tree rval, type;      /* Subscripting with type char is likely to lose	 on a machine where chars are signed.	 So warn on any machine, but optionally.	 Don't warn for unsigned char since that type is safe.	 Don't warn for signed char because anyone who uses that	 must have done so deliberately.  */      if (warn_char_subscripts	  && TYPE_MAIN_VARIANT (TREE_TYPE (idx)) == char_type_node)	warning ("array subscript has type `char'");      /* Apply default promotions *after* noticing character types.  */      idx = default_conversion (idx);      if (TREE_CODE (TREE_TYPE (idx)) != INTEGER_TYPE)	{	  error ("array subscript is not an integer");	  return error_mark_node;	}      /* An array that is indexed by a non-constant	 cannot be stored in a register; we must be able to do	 address arithmetic on its address.	 Likewise an array of elements of variable size.  */      if (TREE_CODE (idx) != INTEGER_CST	  || (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))) != 0	      && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))	{	  if (mark_addressable (array) == 0)	    return error_mark_node;	}      /* An array that is indexed by a constant value which is not within	 the array bounds cannot be stored in a register either; because we	 would get a crash in store_bit_field/extract_bit_field when trying	 to access a non-existent part of the register.  */      if (TREE_CODE (idx) == INTEGER_CST	  && TYPE_VALUES (TREE_TYPE (array))	  && ! int_fits_type_p (idx, TYPE_VALUES (TREE_TYPE (array))))	{	  if (mark_addressable (array) == 0)	    return error_mark_node;	}      if (pedantic && !lvalue_p (array))	pedwarn ("ANSI C++ forbids subscripting non-lvalue array");      /* Note in C++ it is valid to subscript a `register' array, since	 it is valid to take the address of something with that	 storage specification.  */      if (extra_warnings)	{	  tree foo = array;	  while (TREE_CODE (foo) == COMPONENT_REF)	    foo = TREE_OPERAND (foo, 0);	  if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))	    warning ("subscripting array declared `register'");	}      type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));      rval = build (ARRAY_REF, type, array, idx);      /* Array ref is const/volatile if the array elements are	 or if the array is..  */      TREE_READONLY (rval)	|= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))	    | TREE_READONLY (array));      TREE_SIDE_EFFECTS (rval)	|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))	    | TREE_SIDE_EFFECTS (array));      TREE_THIS_VOLATILE (rval)	|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))	    /* This was added by rms on 16 Nov 91.	       It fixes  vol struct foo *a;  a->elts[1] 	       in an inline function.	       Hope it doesn't break something else.  */	    | TREE_THIS_VOLATILE (array));      return require_complete_type (fold (rval));    }  {    tree ar = default_conversion (array);    tree ind = default_conversion (idx);    /* Put the integer in IND to simplify error checking.  */    if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)      {	tree temp = ar;	ar = ind;	ind = temp;      }    if (ar == error_mark_node)      return ar;    if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE)      {	error ("subscripted value is neither array nor pointer");	return error_mark_node;      }    if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)      {	error ("array subscript is not an integer");	return error_mark_node;      }    return build_indirect_ref (build_binary_op_nodefault (PLUS_EXPR, ar, ind, PLUS_EXPR),			       "array indexing");  }}/* Build a function call to function FUNCTION with parameters PARAMS.   PARAMS is a list--a chain of TREE_LIST nodes--in which the   TREE_VALUE of each node is a parameter-expression.   FUNCTION's data type may be a function type or a pointer-to-function.   For C++: If FUNCTION's data type is a TREE_LIST, then the tree list   is the list of possible methods that FUNCTION could conceivably   be.  If the list of methods comes from a class, then it will be   a list of lists (where each element is associated with the class   that produced it), otherwise it will be a simple list (for   functions overloaded in global scope).   In the first case, TREE_VALUE (function) is the head of one of those   lists, and TREE_PURPOSE is the name of the function.   In the second case, TREE_PURPOSE (function) is the function's   name directly.   DECL is the class instance variable, usually CURRENT_CLASS_DECL.  *//* * [eichin:19911015.1726EST] actually return a possibly incomplete * type */treebuild_x_function_call (function, params, decl)     tree function, params, decl;{  tree type;  int is_method;  if (function == error_mark_node)    return error_mark_node;  type = TREE_TYPE (function);  is_method = ((TREE_CODE (function) == TREE_LIST		&& current_class_type != NULL_TREE		&& IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function)) == function)	       || TREE_CODE (function) == IDENTIFIER_NODE	       || TREE_CODE (type) == METHOD_TYPE	       || TYPE_PTRMEMFUNC_P (type));  /* Handle methods, friends, and overloaded functions, respectively.  */  if (is_method)    {      if (TREE_CODE (function) == FUNCTION_DECL)	{	  if (DECL_NAME (function))	    function = DECL_NAME (function);	  else	    function = TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function));	}      else if (TREE_CODE (function) == TREE_LIST)	{#if 0	  if (TREE_CODE (TREE_VALUE (function)) == TREE_LIST)	    function = TREE_PURPOSE (TREE_VALUE (function));	  else	    function = TREE_PURPOSE (function);#else	  my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312);	  function = TREE_PURPOSE (function);#endif	}      else if (TREE_CODE (function) != IDENTIFIER_NODE)	{	  if (TREE_CODE (function) == OFFSET_REF)	    {	      if (TREE_OPERAND (function, 0))		decl = TREE_OPERAND (function, 0);	    }	  /* Call via a pointer to member function.  */	  if (decl == NULL_TREE)	    {	      error ("pointer to member function called, but not in class scope");	      return error_mark_node;	    }	  /* What other type of POINTER_TYPE could this be? */	  if (TREE_CODE (TREE_TYPE (function)) != POINTER_TYPE	      && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (function))	      && TREE_CODE (function) != OFFSET_REF)	    function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE, function);	  goto do_x_function;	}      /* this is an abbreviated method call.         must go through here in case it is a virtual function.	 @@ Perhaps this could be optimized.  */      if (decl == NULL_TREE)	{	  if (current_class_type == NULL_TREE)	    {	      error ("object missing in call to method `%s'",		     IDENTIFIER_POINTER (function));	      return error_mark_node;	    }	  /* Yow: call from a static member function.  */	  decl = build1 (NOP_EXPR, build_pointer_type (current_class_type),			 error_mark_node);	  decl = build_indirect_ref (decl, NULL_PTR);	}      return build_method_call (decl, function, params,				NULL_TREE, LOOKUP_NORMAL);    }  else if (TREE_CODE (function) == COMPONENT_REF	   && type == unknown_type_node)    {      /* Should we undo what was done in build_component_ref? */      if (TREE_CODE (TREE_PURPOSE (TREE_OPERAND (function, 1))) == TREE_VEC)	/* Get the name that build_component_ref hid. */	function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1)));      else	function = TREE_PURPOSE (TREE_OPERAND (function, 1));      return build_method_call (decl, function, params,				NULL_TREE, LOOKUP_NORMAL);    }  else if (TREE_CODE (function) == TREE_LIST)    {      if (TREE_VALUE (function) == NULL_TREE)	{	  cp_error ("function `%D' declared overloaded, but no definitions appear with which to resolve it?!?",		    TREE_PURPOSE (function));	  return error_mark_node;	}      else	{	  tree val = TREE_VALUE (function);	  if (TREE_CODE (val) == TEMPLATE_DECL)	    return build_overload_call_maybe	      (function, params, LOOKUP_COMPLAIN, (struct candidate *)0);	  else if (DECL_CHAIN (val) != NULL_TREE)	    return build_overload_call	      (function, params, LOOKUP_COMPLAIN, (struct candidate *)0);	  else	    my_friendly_abort (360);	}    } do_x_function:  if (TREE_CODE (function) == OFFSET_REF)    {      /* If the component is a data element (or a virtual function), we play	 games here to make things work.  */      tree decl_addr;      if (TREE_OPERAND (function, 0))	decl = TREE_OPERAND (function, 0);      else	decl = C_C_D;      decl_addr = build_unary_op (ADDR_EXPR, decl, 0);      function = get_member_function_from_ptrfunc (&decl_addr,						   TREE_OPERAND (function, 1));      params = tree_cons (NULL_TREE, decl_addr, params);      return build_fu

⌨️ 快捷键说明

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