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

📄 init.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
}treeget_type_value (name)     tree name;{  if (name == error_mark_node)    return NULL_TREE;  if (IDENTIFIER_HAS_TYPE_VALUE (name))    return IDENTIFIER_TYPE_VALUE (name);  else    return NULL_TREE;}  /* This code could just as well go in `class.c', but is placed here for   modularity.  *//* For an expression of the form CNAME :: NAME (PARMLIST), build   the appropriate function call.  */treebuild_member_call (cname, name, parmlist)     tree cname, name, parmlist;{  tree type, t;  tree method_name = name;  int dtor = 0;  int dont_use_this = 0;  tree basetype_path, decl;  if (TREE_CODE (method_name) == BIT_NOT_EXPR)    {      method_name = TREE_OPERAND (method_name, 0);      dtor = 1;    }  if (TREE_CODE (cname) == SCOPE_REF)    cname = resolve_scope_to_name (NULL_TREE, cname);  /* This shouldn't be here, and build_member_call shouldn't appear in     parse.y!  (mrs)  */  if (cname && get_aggr_from_typedef (cname, 0) == 0      && TREE_CODE (cname) == IDENTIFIER_NODE)    {      tree ns = lookup_name (cname, 0);      if (ns && TREE_CODE (ns) == NAMESPACE_DECL)	{	  return build_x_function_call (build_offset_ref (cname, name), parmlist, current_class_decl);	}    }  if (cname == NULL_TREE || ! (type = get_aggr_from_typedef (cname, 1)))    return error_mark_node;  /* An operator we did not like.  */  if (name == NULL_TREE)    return error_mark_node;  if (dtor)    {#if 0      /* Everything can explicitly call a destructor; see 12.4 */      if (! TYPE_HAS_DESTRUCTOR (type))	cp_error ("type `%#T' does not have a destructor", type);      else#endif      cp_error ("cannot call destructor `%T::~%T' without object", type,		method_name);      return error_mark_node;    }  /* No object?  Then just fake one up, and let build_method_call     figure out what to do.  */  if (current_class_type == 0      || get_base_distance (type, current_class_type, 0, &basetype_path) == -1)    dont_use_this = 1;  if (dont_use_this)    {      basetype_path = TYPE_BINFO (type);      decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);    }  else if (current_class_decl == 0)    {      dont_use_this = 1;      decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);    }  else    {      tree olddecl = current_class_decl;      tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));      if (oldtype != type)	{	  tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),					     TYPE_VOLATILE (oldtype));	  decl = convert_force (build_pointer_type (newtype), olddecl, 0);	}      else	decl = olddecl;    }  decl = build_indirect_ref (decl, NULL_PTR);  if (method_name == constructor_name (type)      || method_name == constructor_name_full (type))    return build_functional_cast (type, parmlist);  if (t = lookup_fnfields (basetype_path, method_name, 0))    return build_method_call (decl, method_name, parmlist, basetype_path,			      LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);  if (TREE_CODE (name) == IDENTIFIER_NODE      && ((t = lookup_field (TYPE_BINFO (type), name, 1, 0))))    {      if (t == error_mark_node)	return error_mark_node;      if (TREE_CODE (t) == FIELD_DECL)	{	  if (dont_use_this)	    {	      cp_error ("invalid use of non-static field `%D'", t);	      return error_mark_node;	    }	  decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t);	}      else if (TREE_CODE (t) == VAR_DECL)	decl = t;      else	{	  cp_error ("invalid use of member `%D'", t);	  return error_mark_node;	}      if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl))	  && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (decl)))	return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl, parmlist, NULL_TREE);      return build_function_call (decl, parmlist);    }  else    {      cp_error ("no method `%T::%D'", type, name);      return error_mark_node;    }}/* Build a reference to a member of an aggregate.  This is not a   C++ `&', but really something which can have its address taken,   and then act as a pointer to member, for example CNAME :: FIELD   can have its address taken by saying & CNAME :: FIELD.   @@ Prints out lousy diagnostics for operator <typename>   @@ fields.   @@ This function should be rewritten and placed in search.c.  */treebuild_offset_ref (cname, name)     tree cname, name;{  tree decl, type, fnfields, fields, t = error_mark_node;  tree basetypes = NULL_TREE;  int dtor = 0;  if (TREE_CODE (cname) == SCOPE_REF)    cname = resolve_scope_to_name (NULL_TREE, cname);  /* Handle namespace names fully here.  */  if (TREE_CODE (cname) == IDENTIFIER_NODE      && get_aggr_from_typedef (cname, 0) == 0)    {      tree ns = lookup_name (cname, 0);      tree val;      if (ns && TREE_CODE (ns) == NAMESPACE_DECL)	{	  val = lookup_namespace_name (ns, name);	  if (val)	    return val;	  cp_error ("namespace `%D' has no member named `%D'", ns, name);	  return error_mark_node;	}    }  if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1))    return error_mark_node;  type = IDENTIFIER_TYPE_VALUE (cname);  if (TREE_CODE (name) == BIT_NOT_EXPR)    {      dtor = 1;      name = TREE_OPERAND (name, 0);    }  if (TYPE_SIZE (type) == 0)    {      t = IDENTIFIER_CLASS_VALUE (name);      if (t == 0)	{	  cp_error ("incomplete type `%T' does not have member `%D'", type,		      name);	  return error_mark_node;	}      if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL	  || TREE_CODE (t) == CONST_DECL)	{	  TREE_USED (t) = 1;	  return t;	}      if (TREE_CODE (t) == FIELD_DECL)	sorry ("use of member in incomplete aggregate type");      else if (TREE_CODE (t) == FUNCTION_DECL)	sorry ("use of member function in incomplete aggregate type");      else	my_friendly_abort (52);      return error_mark_node;    }#if 0  if (TREE_CODE (name) == TYPE_EXPR)    /* Pass a TYPE_DECL to build_component_type_expr.  */    return build_component_type_expr (TYPE_NAME (TREE_TYPE (cname)),				      name, NULL_TREE, 1);#endif  if (current_class_type == 0      || get_base_distance (type, current_class_type, 0, &basetypes) == -1)    {      basetypes = TYPE_BINFO (type);      decl = build1 (NOP_EXPR,		     IDENTIFIER_TYPE_VALUE (cname),		     error_mark_node);    }  else if (current_class_decl == 0)    decl = build1 (NOP_EXPR, IDENTIFIER_TYPE_VALUE (cname),		   error_mark_node);  else    decl = C_C_D;  fnfields = lookup_fnfields (basetypes, name, 1);  fields = lookup_field (basetypes, name, 0, 0);  if (fields == error_mark_node || fnfields == error_mark_node)    return error_mark_node;  /* A lot of this logic is now handled in lookup_field and     lookup_fnfield. */  if (fnfields)    {      basetypes = TREE_PURPOSE (fnfields);      /* Go from the TREE_BASELINK to the member function info.  */      t = TREE_VALUE (fnfields);      if (fields)	{	  if (DECL_FIELD_CONTEXT (fields) == DECL_FIELD_CONTEXT (t))	    {	      error ("ambiguous member reference: member `%s' defined as both field and function",		     IDENTIFIER_POINTER (name));	      return error_mark_node;	    }	  if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (fields), DECL_FIELD_CONTEXT (t)))	    ;	  else if (UNIQUELY_DERIVED_FROM_P (DECL_FIELD_CONTEXT (t), DECL_FIELD_CONTEXT (fields)))	    t = fields;	  else	    {	      error ("ambiguous member reference: member `%s' derives from distinct classes in multiple inheritance lattice");	      return error_mark_node;	    }	}      if (t == TREE_VALUE (fnfields))	{	  extern int flag_save_memoized_contexts;	  if (DECL_CHAIN (t) == NULL_TREE || dtor)	    {	      enum access_type access;	      /* unique functions are handled easily.  */	    unique:	      access = compute_access (basetypes, t);	      if (access == access_protected)		{		  cp_error_at ("member function `%#D' is protected", t);		  error ("in this context");		  return error_mark_node;		}	      if (access == access_private)		{		  cp_error_at ("member function `%#D' is private", t);		  error ("in this context");		  return error_mark_node;		}	      assemble_external (t);	      return build (OFFSET_REF, TREE_TYPE (t), decl, t);	    }	  /* overloaded functions may need more work.  */	  if (cname == name)	    {	      if (TYPE_HAS_DESTRUCTOR (type)		  && DECL_CHAIN (DECL_CHAIN (t)) == NULL_TREE)		{		  t = DECL_CHAIN (t);		  goto unique;		}	    }	  /* FNFIELDS is most likely allocated on the search_obstack,	     which will go away after this class scope.  If we need	     to save this value for later (either for memoization	     or for use as an initializer for a static variable), then	     do so here.	     ??? The smart thing to do for the case of saving initializers	     is to resolve them before we're done with this scope.  */	  if (!TREE_PERMANENT (fnfields)	      && ((flag_save_memoized_contexts && global_bindings_p ())		  || ! allocation_temporary_p ()))	    fnfields = copy_list (fnfields);	  for (t = TREE_VALUE (fnfields); t; t = DECL_CHAIN (t))	    assemble_external (t);	  t = build_tree_list (error_mark_node, fnfields);	  TREE_TYPE (t) = build_offset_type (type, unknown_type_node);	  return t;	}    }  /* Now that we know we are looking for a field, see if we     have access to that field.  Lookup_field will give us the     error message.  */  t = lookup_field (basetypes, name, 1, 0);  if (t == error_mark_node)    return error_mark_node;  if (t == NULL_TREE)    {      cp_error ("`%D' is not a member of type `%T'", name, type);      return error_mark_node;    }  if (TREE_CODE (t) == TYPE_DECL)    {      TREE_USED (t) = 1;      return t;    }  /* static class members and class-specific enum     values can be returned without further ado.  */  if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)    {      assemble_external (t);      TREE_USED (t) = 1;      return t;    }  if (TREE_CODE (t) == FIELD_DECL && DECL_BIT_FIELD (t))    {      cp_error ("illegal pointer to bit field `%D'", t);      return error_mark_node;    }  /* static class functions too.  */  if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)    my_friendly_abort (53);  /* In member functions, the form `cname::name' is no longer     equivalent to `this->cname::name'.  */  return build (OFFSET_REF, build_offset_type (type, TREE_TYPE (t)), decl, t);}/* Given an object EXP and a member function reference MEMBER,   return the address of the actual member function.  */treeget_member_function (exp_addr_ptr, exp, member)     tree *exp_addr_ptr;     tree exp, member;{  tree ctype = TREE_TYPE (exp);  tree function = save_expr (build_unary_op (ADDR_EXPR, member, 0));  if (TYPE_VIRTUAL_P (ctype)      || (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (ctype)))    {      tree e0, e1, e3;      tree exp_addr;      /* Save away the unadulterated `this' pointer.  */      exp_addr = save_expr (*exp_addr_ptr);      /* Cast function to signed integer.  */      e0 = build1 (NOP_EXPR, integer_type_node, function);      /* There is a hack here that takes advantage of	 twos complement arithmetic, and the fact that	 there are more than one UNITS to the WORD.	 If the high bit is set for the `function',	 then we pretend it is a virtual function,	 and the array indexing will knock this bit	 out the top, leaving a valid index.  */      if (UNITS_PER_WORD <= 1)	my_friendly_abort (54);      e1 = build (GT_EXPR, boolean_type_node, e0, integer_zero_node);      e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,					   build_tree_list (NULL_TREE, e1)));      e1 = save_expr (e1);      if (TREE_SIDE_EFFECTS (*exp_addr_ptr))	{	  exp = build_indirect_ref (exp_addr, NULL_PTR);	  *exp_addr_ptr = exp_addr;	}      /* This is really hairy: if the function pointer is a pointer	 to a non-virtual member function, then we can't go mucking	 with the `this' pointer (any more than we already have to	 this point).  If it is a pointer to a virtual member function,	 then we have to adjust the `this' pointer according to	 what the virtual function table tells us.  */      e3 = build_vfn_ref (exp_addr_ptr, exp, e0);      my_friendly_assert (e3 != error_mark_node, 213);      /* Change this pointer type from `void *' to the	 type it is really sup

⌨️ 快捷键说明

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