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

📄 cp-init.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
is_aggr_typedef (name, or_else)     tree name;{  tree type;  if (name == error_mark_node)    return 0;  if (! IDENTIFIER_HAS_TYPE_VALUE (name))    {      if (or_else)	error ("`%s' fails to be an aggregate typedef",	       IDENTIFIER_POINTER (name));      return 0;    }  type = IDENTIFIER_TYPE_VALUE (name);  if (! IS_AGGR_TYPE (type))    {      if (or_else)	error ("type `%s' is of non-aggregate type",	       IDENTIFIER_POINTER (name));      return 0;    }  return 1;}/* This code could just as well go in `cp-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);  if (cname == NULL_TREE || ! is_aggr_typedef (cname, 1))    return error_mark_node;  /* An operator we did not like.  */  if (name == NULL_TREE)    return error_mark_node;  if (dtor)    {      if (! TYPE_HAS_DESTRUCTOR (IDENTIFIER_TYPE_VALUE (cname)))	error ("type `%s' does not have a destructor",	       IDENTIFIER_POINTER (cname));      else	error ("destructor specification error");      return error_mark_node;    }  type = IDENTIFIER_TYPE_VALUE (cname);  /* 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 = NULL_TREE;      decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node);    }  else if (current_class_decl == 0)    {      dont_use_this = 1;      decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node);    }  else    {      decl = current_class_decl;      if (TREE_TYPE (decl) != type)	decl = convert (TYPE_POINTER_TO (type), decl);    }  if (t = lookup_fnfields (TYPE_BINFO (type), 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)	    {	      error ("invalid use of non-static field `%s'",		     IDENTIFIER_POINTER (name));	      return error_mark_node;	    }	  decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t);	}      else if (TREE_CODE (t) == VAR_DECL)	decl = t;      else	{	  error ("invalid use of member `%s::%s'",		 IDENTIFIER_POINTER (cname), name);	  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);      return build_function_call (decl, parmlist);    }  else    {      char *err_name;      if (TREE_CODE (name) == IDENTIFIER_NODE)	{	  if (IDENTIFIER_OPNAME_P (name))	    {	      char *op_name = operator_name_string (method_name);	      err_name = (char *)alloca (13 + strlen (op_name));	      sprintf (err_name, "operator %s", op_name);	    }	  else	    err_name = IDENTIFIER_POINTER (name);	}      else	my_friendly_abort (51);      error ("no method `%s::%s'", IDENTIFIER_POINTER (cname), err_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 cp-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);  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)	{	  error_with_aggr_type (type, "incomplete type `%s' does not have member `%s'", IDENTIFIER_POINTER (name));	  return error_mark_node;	}      if (TREE_CODE (t) == TYPE_DECL)	{	  error_with_decl (t, "member `%s' is just a type declaration");	  return error_mark_node;	}      if (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 (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);  fnfields = lookup_fnfields (TYPE_BINFO (type), name, 0);  fields = lookup_field (type, name, 0, 0);  if (fields == error_mark_node)    return error_mark_node;  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;  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;	  /* This does not handle visibility checking yet.  */	  if (DECL_CHAIN (t) == NULL_TREE || dtor)	    {	      enum visibility_type visibility;	      /* unique functions are handled easily.  */	    unique:	      visibility = compute_visibility (basetypes, t);	      if (visibility == visibility_protected)		{		  error_with_decl (t, "member function `%s' is protected");		  error ("in this context");		  return error_mark_node;		}	      if (visibility == visibility_private)		{		  error_with_decl (t, "member function `%s' is private");		  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);	  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)    {      char *print_name;      if (name == ansi_opname[(int) TYPE_EXPR])	{	  error ("type conversion operator not a member of type `%s'",		 IDENTIFIER_POINTER (cname));	  return error_mark_node;	}      print_name = operator_name_string (name);      /* First character of "<invalid operator>".  */      if (print_name[0] == '<')	error ("field `%s' is not a member of type `%s'",	       IDENTIFIER_POINTER (name),	       IDENTIFIER_POINTER (cname));      else	error ("operator `%s' is not a member of type `%s'",	       print_name, IDENTIFIER_POINTER (cname));      return error_mark_node;    }  if (TREE_CODE (t) == TYPE_DECL)    {      error_with_decl (t, "member `%s' is just a type declaration");      return error_mark_node;    }  /* 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;    }  /* 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);#ifdef VTABLE_USES_MASK      /* If we are willing to limit the number of	 virtual functions a class may have to some	 *small* number, then if, for a function address,	 we are passed some small number, we know that	 it is a virtual function index, and work from there.  */      e1 = build (BIT_AND_EXPR, integer_type_node, e0, vtbl_mask);#else      /* 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, integer_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);#endif      if (TREE_SIDE_EFFECTS (*exp_addr_ptr))	{	  exp = build_indirect_ref (exp_addr

⌨️ 快捷键说明

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