FreeBSD/contrib/gcc/cp/class.c
/* Add method METHOD to class TYPE.  If USING_DECL is non-null, it is
   the USING_DECL naming METHOD.  Returns true if the method could be
   added to the method vec.  */
Add method METHOD to class TYPE.  If USING_DECL is non-null, it is
the USING_DECL naming METHOD.  Returns true if the method could be
added to the method vec.
Add method METHOD to class TYPE . If USING_DECL is non - null it is the USING_DECL naming METHOD . Returns true if the method could be added to the method vec .
bool
add_method (tree type, tree method, tree using_decl)
{
  unsigned slot;
  tree overload;
  bool template_conv_p = false;
  bool conv_p;
  VEC(tree,gc) *method_vec;
  bool complete_p;
  bool insert_p = false;
  tree current_fns;
  if (method == error_mark_node)
    return false;
  complete_p = COMPLETE_TYPE_P (type);
  conv_p = DECL_CONV_FN_P (method);
  if (conv_p)
    template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
		       && DECL_TEMPLATE_CONV_FN_P (method));
  method_vec = CLASSTYPE_METHOD_VEC (type);
  if (!method_vec)
    {
      method_vec = VEC_alloc (tree, gc, 8);
      VEC_quick_push (tree, method_vec, NULL_TREE);
      VEC_quick_push (tree, method_vec, NULL_TREE);
      CLASSTYPE_METHOD_VEC (type) = method_vec;
    }
  grok_special_member_properties (method);
  if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
    slot = CLASSTYPE_CONSTRUCTOR_SLOT;
  else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
    {
      slot = CLASSTYPE_DESTRUCTOR_SLOT;
      if (TYPE_FOR_JAVA (type))
	{
	  if (!DECL_ARTIFICIAL (method))
	    error ("Java class %qT cannot have a destructor", type);
	  else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
	    error ("Java class %qT cannot have an implicit non-trivial "
		   "destructor",
		   type);
	}
    }
  else
    {
      tree m;
      insert_p = true;
      for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
	   VEC_iterate (tree, method_vec, slot, m);
	   ++slot)
	{
	  m = OVL_CURRENT (m);
	  if (template_conv_p)
	    {
	      if (TREE_CODE (m) == TEMPLATE_DECL
		  && DECL_TEMPLATE_CONV_FN_P (m))
		insert_p = false;
	      break;
	    }
	  if (conv_p && !DECL_CONV_FN_P (m))
	    break;
	  if (DECL_NAME (m) == DECL_NAME (method))
	    {
	      insert_p = false;
	      break;
	    }
	  if (complete_p
	      && !DECL_CONV_FN_P (m)
	      && DECL_NAME (m) > DECL_NAME (method))
	    break;
	}
    }
  current_fns = insert_p ? NULL_TREE : VEC_index (tree, method_vec, slot);
  if (processing_template_decl)
    ;
  else
    {
      tree fns;
      for (fns = current_fns; fns; fns = OVL_NEXT (fns))
	{
	  tree fn = OVL_CURRENT (fns);
	  tree fn_type;
	  tree method_type;
	  tree parms1;
	  tree parms2;
	  if (TREE_CODE (fn) != TREE_CODE (method))
	    continue;
	  fn_type = TREE_TYPE (fn);
	  method_type = TREE_TYPE (method);
	  parms1 = TYPE_ARG_TYPES (fn_type);
	  parms2 = TYPE_ARG_TYPES (method_type);
	  if (! DECL_STATIC_FUNCTION_P (fn)
	      && ! DECL_STATIC_FUNCTION_P (method)
	      && (TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms1)))
		  != TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms2)))))
	    continue;
	  if (TREE_CODE (fn) == TEMPLATE_DECL
	      && (!same_type_p (TREE_TYPE (fn_type),
				TREE_TYPE (method_type))
		  || !comp_template_parms (DECL_TEMPLATE_PARMS (fn),
					   DECL_TEMPLATE_PARMS (method))))
	    continue;
	  if (! DECL_STATIC_FUNCTION_P (fn))
	    parms1 = TREE_CHAIN (parms1);
	  if (! DECL_STATIC_FUNCTION_P (method))
	    parms2 = TREE_CHAIN (parms2);
	  if (compparms (parms1, parms2)
	      && (!DECL_CONV_FN_P (fn)
		  || same_type_p (TREE_TYPE (fn_type),
				  TREE_TYPE (method_type))))
	    {
	      if (using_decl)
		{
		  if (DECL_CONTEXT (fn) == type)
		    return false;
		  if (DECL_CONTEXT (fn) == DECL_CONTEXT (method))
		    error ("repeated using declaration %q+D", using_decl);
		  else
		    error ("using declaration %q+D conflicts with a previous using declaration",
			   using_decl);
		}
	      else
		{
		  error ("%q+#D cannot be overloaded", method);
		  error ("with %q+#D", fn);
		}
	      return false;
	    }
	}
    }
  if (current_fns && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
    return false;
  overload = build_overload (method, current_fns);
  if (conv_p)
    TYPE_HAS_CONVERSION (type) = 1;
  else if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
    push_class_level_binding (DECL_NAME (method), overload);
  if (insert_p)
    {
      bool reallocated;
      if (complete_p)
	reallocated = VEC_reserve_exact (tree, gc, method_vec, 1);
      else
	reallocated = VEC_reserve (tree, gc, method_vec, 1);
      if (reallocated)
	CLASSTYPE_METHOD_VEC (type) = method_vec;
      if (slot == VEC_length (tree, method_vec))
	VEC_quick_push (tree, method_vec, overload);
      else
	VEC_quick_insert (tree, method_vec, slot, overload);
    }
  else
    VEC_replace (tree, method_vec, slot, overload);
  return true;
}
bool add_method ( tree type , tree method , tree using_decl ) { unsigned slot ; tree overload ; bool template_conv_p = false ; bool conv_p ; VEC ( tree , gc ) * method_vec ; bool complete_p ; bool insert_p = false ; tree current_fns ; if ( method == error_mark_node ) return false ; complete_p = COMPLETE_TYPE_P ( type ) ; conv_p = DECL_CONV_FN_P ( method ) ; if ( conv_p ) template_conv_p = ( TREE_CODE ( method ) == TEMPLATE_DECL && DECL_TEMPLATE_CONV_FN_P ( method ) ) ; method_vec = CLASSTYPE_METHOD_VEC ( type ) ; if ( ! method_vec ) { method_vec = VEC_alloc ( tree , gc , 8 ) ; VEC_quick_push ( tree , method_vec , NULL_TREE ) ; VEC_quick_push ( tree , method_vec , NULL_TREE ) ; CLASSTYPE_METHOD_VEC ( type ) = method_vec ; } grok_special_member_properties ( method ) ; if ( DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P ( method ) ) slot = CLASSTYPE_CONSTRUCTOR_SLOT ; else if ( DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P ( method ) ) { slot = CLASSTYPE_DESTRUCTOR_SLOT ; if ( TYPE_FOR_JAVA ( type ) ) { if ( ! DECL_ARTIFICIAL ( method ) ) error ( " " , type ) ; else if ( TYPE_HAS_NONTRIVIAL_DESTRUCTOR ( type ) ) error ( " " " " , type ) ; } } else { tree m ; insert_p = true ; for ( slot = CLASSTYPE_FIRST_CONVERSION_SLOT ; VEC_iterate ( tree , method_vec , slot , m ) ; ++ slot ) { m = OVL_CURRENT ( m ) ; if ( template_conv_p ) { if ( TREE_CODE ( m ) == TEMPLATE_DECL && DECL_TEMPLATE_CONV_FN_P ( m ) ) insert_p = false ; break ; } if ( conv_p && ! DECL_CONV_FN_P ( m ) ) break ; if ( DECL_NAME ( m ) == DECL_NAME ( method ) ) { insert_p = false ; break ; } if ( complete_p && ! DECL_CONV_FN_P ( m ) && DECL_NAME ( m ) > DECL_NAME ( method ) ) break ; } } current_fns = insert_p ? NULL_TREE : VEC_index ( tree , method_vec , slot ) ; if ( processing_template_decl ) ; else { tree fns ; for ( fns = current_fns ; fns ; fns = OVL_NEXT ( fns ) ) { tree fn = OVL_CURRENT ( fns ) ; tree fn_type ; tree method_type ; tree parms1 ; tree parms2 ; if ( TREE_CODE ( fn ) != TREE_CODE ( method ) ) continue ; fn_type = TREE_TYPE ( fn ) ; method_type = TREE_TYPE ( method ) ; parms1 = TYPE_ARG_TYPES ( fn_type ) ; parms2 = TYPE_ARG_TYPES ( method_type ) ; if ( ! DECL_STATIC_FUNCTION_P ( fn ) && ! DECL_STATIC_FUNCTION_P ( method ) && ( TYPE_QUALS ( TREE_TYPE ( TREE_VALUE ( parms1 ) ) ) != TYPE_QUALS ( TREE_TYPE ( TREE_VALUE ( parms2 ) ) ) ) ) continue ; if ( TREE_CODE ( fn ) == TEMPLATE_DECL && ( ! same_type_p ( TREE_TYPE ( fn_type ) , TREE_TYPE ( method_type ) ) || ! comp_template_parms ( DECL_TEMPLATE_PARMS ( fn ) , DECL_TEMPLATE_PARMS ( method ) ) ) ) continue ; if ( ! DECL_STATIC_FUNCTION_P ( fn ) ) parms1 = TREE_CHAIN ( parms1 ) ; if ( ! DECL_STATIC_FUNCTION_P ( method ) ) parms2 = TREE_CHAIN ( parms2 ) ; if ( compparms ( parms1 , parms2 ) && ( ! DECL_CONV_FN_P ( fn ) || same_type_p ( TREE_TYPE ( fn_type ) , TREE_TYPE ( method_type ) ) ) ) { if ( using_decl ) { if ( DECL_CONTEXT ( fn ) == type ) return false ; if ( DECL_CONTEXT ( fn ) == DECL_CONTEXT ( method ) ) error ( " " , using_decl ) ; else error ( " " , using_decl ) ; } else { error ( " " , method ) ; error ( " " , fn ) ; } return false ; } } } if ( current_fns && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P ( method ) ) return false ; overload = build_overload ( method , current_fns ) ; if ( conv_p ) TYPE_HAS_CONVERSION ( type ) = 1 ; else if ( slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && ! complete_p ) push_class_level_binding ( DECL_NAME ( method ) , overload ) ; if ( insert_p ) { bool reallocated ; if ( complete_p ) reallocated = VEC_reserve_exact ( tree , gc , method_vec , 1 ) ; else reallocated = VEC_reserve ( tree , gc , method_vec , 1 ) ; if ( reallocated ) CLASSTYPE_METHOD_VEC ( type ) = method_vec ; if ( slot == VEC_length ( tree , method_vec ) ) VEC_quick_push ( tree , method_vec , overload ) ; else VEC_quick_insert ( tree , method_vec , slot , overload ) ; } else VEC_replace ( tree , method_vec , slot , overload ) ; return true ; }
Add method METHOD to class TYPE.
Add method METHOD to class TYPE .
/* Make a new method vector.  We start with 8 entries.  We must
	 allocate at least two (for constructors and destructors), and
	 we're going to end up with an assignment operator at some
	 point as well.  */ /* Create slots for constructors and destructors.  */ /* Maintain TYPE_HAS_CONSTRUCTOR, etc.  */ /* Constructors and destructors go in special slots.  */ /* See if we already have an entry with this name.  */ /* TYPE is a template class.  Don't issue any errors now; wait
       until instantiation time to complain.  */ /* Check to see if we've already got this method.  */ /* [over.load] Member function declarations with the
	     same name and the same parameter types cannot be
	     overloaded if any of them is a static member
	     function declaration.

	     [namespace.udecl] When a using-declaration brings names
	     from a base class into a derived class scope, member
	     functions in the derived class override and/or hide member
	     functions with the same name and parameter types in a base
	     class (rather than conflicting).  */ /* Compare the quals on the 'this' parm.  Don't compare
	     the whole types, as used functions are treated as
	     coming from the using class in overload resolution.  */ /* For templates, the return type and template parameters
	     must be identical.  */ /* Defer to the local function.  */ /* We don't call duplicate_decls here to merge the
		 declarations because that will confuse things if the
		 methods have inline definitions.  In particular, we
		 will crash while processing the definitions.  */ /* A class should never have more than one destructor.  */ /* Add the new binding.  */ /* We only expect to add few methods in the COMPLETE_P case, so
	 just make room for one more method in that case.  */ /* Replace the current slot.  */