method.c

来自「GCC编译器源代码」· C语言 代码 · 共 2,227 行 · 第 1/4 页

C
2,227
字号
	      if (DECL_CHAIN (fndecl) == NULL_TREE)		{		  warning ("methods cannot be converted to function pointers");		  return fndecl;		}	      else		{		  error ("ambiguous request for method pointer `%s'",			 IDENTIFIER_POINTER (name));		  return error_mark_node;		}	    }	}      if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name))	{	  return IDENTIFIER_LABEL_VALUE (name);	}      return error_mark_node;    }  type = TREE_TYPE (value);  if (TREE_CODE (value) == FIELD_DECL)    {      if (current_class_ptr == NULL_TREE)	{	  error ("request for member `%s' in static member function",		 IDENTIFIER_POINTER (DECL_NAME (value)));	  return error_mark_node;	}      TREE_USED (current_class_ptr) = 1;      /* Mark so that if we are in a constructor, and then find that	 this field was initialized by a base initializer,	 we can emit an error message.  */      TREE_USED (value) = 1;      value = build_component_ref (current_class_ref, name, NULL_TREE, 1);    }  else if (really_overloaded_fn (value))    {#if 0      tree t = get_first_fn (value);      for (; t; t = DECL_CHAIN (t))	{	  if (TREE_CODE (t) == TEMPLATE_DECL)	    continue;	  assemble_external (t);	  TREE_USED (t) = 1;	}#endif    }  else if (TREE_CODE (value) == TREE_LIST)    {      /* Ambiguous reference to base members, possibly other cases?.  */      tree t = value;      while (t && TREE_CODE (t) == TREE_LIST)	{	  mark_used (TREE_VALUE (t));	  t = TREE_CHAIN (t);	}    }  else    mark_used (value);  if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL)    {      tree context = decl_function_context (value);      if (context != NULL_TREE && context != current_function_decl	  && ! TREE_STATIC (value))	{	  cp_error ("use of %s from containing function",		      (TREE_CODE (value) == VAR_DECL		       ? "`auto' variable" : "parameter"));	  cp_error_at ("  `%#D' declared here", value);	  value = error_mark_node;	}    }  if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))    {      if (DECL_LANG_SPECIFIC (value)	  && DECL_CLASS_CONTEXT (value) != current_class_type)	{	  tree path, access;	  register tree context	    = (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value))	      ? DECL_CLASS_CONTEXT (value)	      : DECL_CONTEXT (value);	  get_base_distance (context, current_class_type, 0, &path);	  if (path)	    {	      access = compute_access (path, value);	      if (access != access_public_node)		{		  if (TREE_CODE (value) == VAR_DECL)		    error ("static member `%s' is %s",			   IDENTIFIER_POINTER (name),			   TREE_PRIVATE (value) ? "private"						: "from a private base class");		  else		    error ("enum `%s' is from private base class",			   IDENTIFIER_POINTER (name));		  return error_mark_node;		}	    }	}    }  else if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value))    {      if (type == 0)	{	  error ("request for member `%s' is ambiguous in multiple inheritance lattice",		 IDENTIFIER_POINTER (name));	  return error_mark_node;	}      return value;    }  if (TREE_CODE (type) == REFERENCE_TYPE && ! processing_template_decl)    value = convert_from_reference (value);  return value;}static char *thunk_printable_name (decl)     tree decl;{  return "<thunk function>";}treemake_thunk (function, delta)     tree function;     int delta;{  char buffer[250];  tree thunk_id;  tree thunk;  char *func_name;  tree func_decl;  if (TREE_CODE (function) != ADDR_EXPR)    abort ();  func_decl = TREE_OPERAND (function, 0);  if (TREE_CODE (func_decl) != FUNCTION_DECL)    abort ();  func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl));  if (delta<=0)    sprintf (buffer, "__thunk_%d_%s", -delta, func_name);  else    sprintf (buffer, "__thunk_n%d_%s", delta, func_name);  thunk_id = get_identifier (buffer);  thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);  if (thunk && TREE_CODE (thunk) != THUNK_DECL)    {      cp_error ("implementation-reserved name `%D' used", thunk_id);      IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE;    }  if (thunk == NULL_TREE)    {      thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));      TREE_READONLY (thunk) = TREE_READONLY (func_decl);      TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);      comdat_linkage (thunk);      TREE_SET_CODE (thunk, THUNK_DECL);      DECL_INITIAL (thunk) = function;      THUNK_DELTA (thunk) = delta;      DECL_EXTERNAL (thunk) = 1;      DECL_ARTIFICIAL (thunk) = 1;      /* So that finish_file can write out any thunks that need to be: */      pushdecl_top_level (thunk);    }  return thunk;}/* Emit the definition of a C++ multiple inheritance vtable thunk.  */voidemit_thunk (thunk_fndecl)     tree thunk_fndecl;{  tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0);  int delta = THUNK_DELTA (thunk_fndecl);  if (TREE_ASM_WRITTEN (thunk_fndecl))    return;  TREE_ASM_WRITTEN (thunk_fndecl) = 1;  TREE_ADDRESSABLE (function) = 1;  mark_used (function);  if (current_function_decl)    abort ();  TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);  {#ifdef ASM_OUTPUT_MI_THUNK    char *fnname;    current_function_decl = thunk_fndecl;    /* Make sure we build up its RTL before we go onto the       temporary obstack.  */    make_function_rtl (thunk_fndecl);    temporary_allocation ();    DECL_RESULT (thunk_fndecl)      = build_decl (RESULT_DECL, 0, integer_type_node);    fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);    init_function_start (thunk_fndecl, input_filename, lineno);    assemble_start_function (thunk_fndecl, fnname);    ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);    assemble_end_function (thunk_fndecl, fnname);    permanent_allocation (1);    current_function_decl = 0;#else /* ASM_OUTPUT_MI_THUNK */  /* If we don't have the necessary macro for efficient thunks, generate a     thunk function that just makes a call to the real function.     Unfortunately, this doesn't work for varargs.  */    tree a, t;    if (varargs_function_p (function))      cp_error ("generic thunk code fails for method `%#D' which uses `...'",		function);    /* Set up clone argument trees for the thunk.  */    t = NULL_TREE;    for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))      {	tree x = copy_node (a);	TREE_CHAIN (x) = t;	DECL_CONTEXT (x) = thunk_fndecl;	t = x;      }    a = nreverse (t);    DECL_ARGUMENTS (thunk_fndecl) = a;    DECL_RESULT (thunk_fndecl) = NULL_TREE;    DECL_LANG_SPECIFIC (thunk_fndecl) = DECL_LANG_SPECIFIC (function);    copy_lang_decl (thunk_fndecl);    DECL_INTERFACE_KNOWN (thunk_fndecl) = 1;    DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1;    start_function (NULL_TREE, thunk_fndecl, NULL_TREE, 1);    store_parm_decls ();    current_function_is_thunk = 1;    /* Build up the call to the real function.  */    t = build_int_2 (delta, -1 * (delta < 0));    TREE_TYPE (t) = signed_type (sizetype);    t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t));    t = expr_tree_cons (NULL_TREE, t, NULL_TREE);    for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))      t = expr_tree_cons (NULL_TREE, a, t);    t = nreverse (t);    t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t);    c_expand_return (t);    finish_function (lineno, 0, 0);    /* Don't let the backend defer this function.  */    if (DECL_DEFER_OUTPUT (thunk_fndecl))      {	output_inline_function (thunk_fndecl);	permanent_allocation (1);      }#endif /* ASM_OUTPUT_MI_THUNK */  }  TREE_SET_CODE (thunk_fndecl, THUNK_DECL);}/* Code for synthesizing methods which have default semantics defined.  *//* For the anonymous union in TYPE, return the member that is at least as   large as the rest of the members, so we can copy it.  */static treelargest_union_member (type)     tree type;{  tree f, type_size = TYPE_SIZE (type);  for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))    if (simple_cst_equal (DECL_SIZE (f), type_size) == 1)      return f;  /* We should always find one.  */  my_friendly_abort (323);  return NULL_TREE;}/* Generate code for default X(X&) constructor.  */static voiddo_build_copy_constructor (fndecl)     tree fndecl;{  tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));  tree t;  clear_last_expr ();  push_momentary ();  if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))    parm = TREE_CHAIN (parm);  parm = convert_from_reference (parm);  if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))    {      t = build (INIT_EXPR, void_type_node, current_class_ref, parm);      TREE_SIDE_EFFECTS (t) = 1;      cplus_expand_expr_stmt (t);    }  else    {      tree fields = TYPE_FIELDS (current_class_type);      int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);      tree binfos = TYPE_BINFO_BASETYPES (current_class_type);      int i;      for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;	   t = TREE_CHAIN (t))	{	  tree basetype = BINFO_TYPE (t);	  tree p = convert_to_reference	    (build_reference_type (basetype), parm,	     CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);	  p = convert_from_reference (p);	  if (p == error_mark_node)	    cp_error ("in default copy constructor");	  else 	    current_base_init_list = tree_cons (basetype,						p, current_base_init_list);	}	      for (i = 0; i < n_bases; ++i)	{	  tree p, basetype = TREE_VEC_ELT (binfos, i);	  if (TREE_VIA_VIRTUAL (basetype))	    continue; 	  basetype = BINFO_TYPE (basetype);	  p = convert_to_reference	    (build_reference_type (basetype), parm,	     CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);	  if (p == error_mark_node) 	    cp_error ("in default copy constructor");	  else 	    {	      p = convert_from_reference (p);	      current_base_init_list = tree_cons (basetype,						  p, current_base_init_list);	    }	}      for (; fields; fields = TREE_CHAIN (fields))	{	  tree init, t;	  tree field = fields;	  if (TREE_CODE (field) != FIELD_DECL)	    continue;	  init = parm;	  if (DECL_NAME (field))	    {	      if (VFIELD_NAME_P (DECL_NAME (field)))		continue;	      if (VBASE_NAME_P (DECL_NAME (field)))		continue;	      /* True for duplicate members.  */	      if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field)		continue;	    }	  else if ((t = TREE_TYPE (field)) != NULL_TREE		   && TREE_CODE (t) == UNION_TYPE		   && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))		   && TYPE_FIELDS (t) != NULL_TREE)	    {	      do		{		  init = build (COMPONENT_REF, t, init, field);		  field = largest_union_member (t);		}	      while ((t = TREE_TYPE (field)) != NULL_TREE		     && TREE_CODE (t) == UNION_TYPE		     && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))		     && TYPE_FIELDS (t) != NULL_TREE);	    }	  else	    continue;	  init = build (COMPONENT_REF, TREE_TYPE (field), init, field);	  init = build_tree_list (NULL_TREE, init);	  current_member_init_list	    = tree_cons (DECL_NAME (field), init, current_member_init_list);	}      current_member_init_list = nreverse (current_member_init_list);      current_base_init_list = nreverse (current_base_init_list);      setup_vtbl_ptr ();    }  pop_momentary ();}static voiddo_build_assign_ref (fndecl)     tree fndecl;{  tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));  clear_last_expr ();  push_momentary ();  parm = convert_from_reference (parm);  if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))    {      tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm);      TREE_SIDE_EFFECTS (t) = 1;      cplus_expand_expr_stmt (t);    }  else    {      tree fields = TYPE_FIELDS (current_class_type);      int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);      tree binfos = TYPE_BINFO_BASETYPES (current_class_type);      int i;      for (i = 0; i < n_bases; ++i)	{	  tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));	  tree p = convert_to_reference	    (build_reference_type (basetype), parm,	     CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);	  p = convert_from_reference (p);	  p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],				 build_expr_list (NULL_TREE, p));	  expand_expr_stmt (p);	}      for (; fields; fields = TREE_CHAIN (fields))	{	  tree comp, init, t;	  tree field = fields;	  if (TREE_CODE (field) != FIELD_DECL)	    continue;	  if (TREE_READONLY (field))	    {	      if (DECL_NAME (field))		cp_error ("non-static const member `%#D', can't use default assignment operator", field);	      else		cp_error ("non-static const member in type `%T', can't use default assignment operator", current_class_type);	      continue;	    }	  else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)	    {	      if (DECL_NAME (field))		cp_error ("non-static reference member `%#D', can't use default assignment operator", field);	      else		cp_error ("non-static reference member in type `%T', can't use default assignment operator", current_class_type);	      continue;	    }	  comp = current_class_ref;	  init = parm;	  if (DECL_NAME (field))	    {	      if (VFIELD_NAME_P (DECL_NAME (field)))		continue;	      if (VBASE_NAME_P (DECL_NAME (field)))		continue;	      /* True for duplicate members.  */	      if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field)		continue;	    }	  else if ((t = TREE_TYPE (field)) != NULL_TREE		   && TREE_CODE (t) == UNION_TYPE		   && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))		   && TYPE_FIELDS (t) != NULL_TREE)	    {	      do		{		  comp = build (COMPONENT_REF, t, comp, field);		  init = build (COMPONENT_REF, t, init, field);		  field = largest_union_member (t);		}	      while ((t = TREE_TYPE (field)) != NULL_TREE		     && TREE_CODE (t) == UNION_TYPE		     && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))		     && TYPE_FIELDS (t) != NULL_TREE);	    }	  else	    continue;	  comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field);	  init = build (COMPONENT_REF, TREE_TYPE (field), init, field);	  expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));	}    }  c_expand_return (current_class_ref);  pop_momentary ();}voidsynthesize_method (fndecl)     tree fndecl;{  int nested = (current_function_decl != NULL_TREE);  tree context = hack_decl_function_context (fndecl);  if (at_eof)    import_export_decl (fndecl);  if (! context)    push_to_top_level ();  else if (nested)    push_cp_function_context (context);  interface_unknown = 1;  start_function (NULL_TREE, fndecl, NULL_TREE, 1);  store_parm_decls ();  if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])    do_build_assign_ref (fndecl);  else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))    ;  else    {      tree arg_chain = FUNCTION_ARG_CHAIN (fndecl);      if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl))	arg_chain = TREE_CHAIN (arg_chain);      if (arg_chain != void_list_node)	do_build_copy_constructor (fndecl);      else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))	setup_vtbl_ptr ();    }  finish_function (lineno, 0, nested);  extract_interface_info ();  if (! context)    pop_from_top_level ();  else if (nested)    pop_cp_function_context (context);}

⌨️ 快捷键说明

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