FreeBSD/contrib/gcc/cp/call.c
/* Build a call to operator delete.  This has to be handled very specially,
   because the restrictions on what signatures match are different from all
   other call instances.  For a normal delete, only a delete taking (void *)
   or (void *, size_t) is accepted.  For a placement delete, only an exact
   match with the placement new is accepted.

   CODE is either DELETE_EXPR or VEC_DELETE_EXPR.
   ADDR is the pointer to be deleted.
   SIZE is the size of the memory block to be deleted.
   GLOBAL_P is true if the delete-expression should not consider
   class-specific delete operators.
   PLACEMENT is the corresponding placement new call, or NULL_TREE.

   If this call to "operator delete" is being generated as part to
   deallocate memory allocated via a new-expression (as per [expr.new]
   which requires that if the initialization throws an exception then
   we call a deallocation function), then ALLOC_FN is the allocation
   function.  */
Build a call to operator delete.  This has to be handled very specially,
because the restrictions on what signatures match are different from all
other call instances.  For a normal delete, only a delete taking (void *)
or (void *, size_t) is accepted.  For a placement delete, only an exact
match with the placement new is accepted.



If this call to "operator delete" is being generated as part to
deallocate memory allocated via a new-expression (as per [expr.new]
which requires that if the initialization throws an exception then
we call a deallocation function), then ALLOC_FN is the allocation
function.
Build a call to operator delete . This has to be handled very specially because the restrictions on what signatures match are different from all other call instances . For a normal delete only a delete taking ( void * ) or ( void * size_t ) is accepted . For a placement delete only an exact match with the placement new is accepted . If this call to " operator delete " is being generated as part to deallocate memory allocated via a new - expression ( as per [ expr . new ] which requires that if the initialization throws an exception then we call a deallocation function ) then ALLOC_FN is the allocation function .
tree
build_op_delete_call (enum tree_code code, tree addr, tree size,
		      bool global_p, tree placement,
		      tree alloc_fn)
{
  tree fn = NULL_TREE;
  tree fns, fnname, argtypes, args, type;
  int pass;
  if (addr == error_mark_node)
    return error_mark_node;
  type = strip_array_types (TREE_TYPE (TREE_TYPE (addr)));
  fnname = ansi_opname (code);
  if (CLASS_TYPE_P (type)
      && COMPLETE_TYPE_P (complete_type (type))
      && !global_p)
    {
      fns = lookup_fnfields (TYPE_BINFO (type), fnname, 1);
      if (fns == error_mark_node)
	return error_mark_node;
    }
  else
    fns = NULL_TREE;
  if (fns == NULL_TREE)
    fns = lookup_name_nonclass (fnname);
  if (placement)
    {
      gcc_assert (alloc_fn != NULL_TREE);
      argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
      args = TREE_CHAIN (TREE_OPERAND (placement, 1));
    }
  else
    {
      argtypes = void_list_node;
      args = NULL_TREE;
    }
  addr = cp_convert (ptr_type_node, addr);
  for (pass = 0; pass < (placement ? 1 : 2); ++pass)
    {
      for (fn = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
	   fn;
	   fn = OVL_NEXT (fn))
	{
	  tree t;
	  t = TYPE_ARG_TYPES (TREE_TYPE (OVL_CURRENT (fn)));
	  if (!same_type_p (TREE_VALUE (t), ptr_type_node))
	    continue;
	  t = TREE_CHAIN (t);
	  if (pass == 0)
	    {
	      tree a = argtypes;
	      while (a && t)
		{
		  if (!same_type_p (TREE_VALUE (a), TREE_VALUE (t)))
		    break;
		  a = TREE_CHAIN (a);
		  t = TREE_CHAIN (t);
		}
	      if (!a && !t)
		break;
	    }
	  else if (pass == 1
		   && t
		   && same_type_p (TREE_VALUE (t), sizetype)
		   && TREE_CHAIN (t) == void_list_node)
	    break;
	}
      if (fn)
	break;
    }
  if (fn)
    {
      fn = OVL_CURRENT (fn);
      if (DECL_CLASS_SCOPE_P (fn))
	perform_or_defer_access_check (TYPE_BINFO (type), fn, fn);
      if (pass == 0)
	args = tree_cons (NULL_TREE, addr, args);
      else
	args = tree_cons (NULL_TREE, addr,
			  build_tree_list (NULL_TREE, size));
      if (placement)
	{
	  mark_used (fn);
	  return build_cxx_call (fn, args);
	}
      else
	return build_function_call (fn, args);
    }
  if (alloc_fn)
    {
      if (!placement)
	warning (0, "no corresponding deallocation function for `%D'", 
		 alloc_fn);
      return NULL_TREE;
    }
  error ("no suitable %<operator %s%> for %qT",
	 operator_name_info[(int)code].name, type);
  return error_mark_node;
}
tree build_op_delete_call ( enum tree_code code , tree addr , tree size , bool global_p , tree placement , tree alloc_fn ) { tree fn = NULL_TREE ; tree fns , fnname , argtypes , args , type ; int pass ; if ( addr == error_mark_node ) return error_mark_node ; type = strip_array_types ( TREE_TYPE ( TREE_TYPE ( addr ) ) ) ; fnname = ansi_opname ( code ) ; if ( CLASS_TYPE_P ( type ) && COMPLETE_TYPE_P ( complete_type ( type ) ) && ! global_p ) { fns = lookup_fnfields ( TYPE_BINFO ( type ) , fnname , 1 ) ; if ( fns == error_mark_node ) return error_mark_node ; } else fns = NULL_TREE ; if ( fns == NULL_TREE ) fns = lookup_name_nonclass ( fnname ) ; if ( placement ) { gcc_assert ( alloc_fn != NULL_TREE ) ; argtypes = TREE_CHAIN ( TYPE_ARG_TYPES ( TREE_TYPE ( alloc_fn ) ) ) ; args = TREE_CHAIN ( TREE_OPERAND ( placement , 1 ) ) ; } else { argtypes = void_list_node ; args = NULL_TREE ; } addr = cp_convert ( ptr_type_node , addr ) ; for ( pass = 0 ; pass < ( placement ? 1 : 2 ) ; ++ pass ) { for ( fn = BASELINK_P ( fns ) ? BASELINK_FUNCTIONS ( fns ) : fns ; fn ; fn = OVL_NEXT ( fn ) ) { tree t ; t = TYPE_ARG_TYPES ( TREE_TYPE ( OVL_CURRENT ( fn ) ) ) ; if ( ! same_type_p ( TREE_VALUE ( t ) , ptr_type_node ) ) continue ; t = TREE_CHAIN ( t ) ; if ( pass == 0 ) { tree a = argtypes ; while ( a && t ) { if ( ! same_type_p ( TREE_VALUE ( a ) , TREE_VALUE ( t ) ) ) break ; a = TREE_CHAIN ( a ) ; t = TREE_CHAIN ( t ) ; } if ( ! a && ! t ) break ; } else if ( pass == 1 && t && same_type_p ( TREE_VALUE ( t ) , sizetype ) && TREE_CHAIN ( t ) == void_list_node ) break ; } if ( fn ) break ; } if ( fn ) { fn = OVL_CURRENT ( fn ) ; if ( DECL_CLASS_SCOPE_P ( fn ) ) perform_or_defer_access_check ( TYPE_BINFO ( type ) , fn , fn ) ; if ( pass == 0 ) args = tree_cons ( NULL_TREE , addr , args ) ; else args = tree_cons ( NULL_TREE , addr , build_tree_list ( NULL_TREE , size ) ) ; if ( placement ) { mark_used ( fn ) ; return build_cxx_call ( fn , args ) ; } else return build_function_call ( fn , args ) ; } if ( alloc_fn ) { if ( ! placement ) warning ( 0 , " " , alloc_fn ) ; return NULL_TREE ; } error ( " " , operator_name_info [ ( int ) code ] . name , type ) ; return error_mark_node ; }
Build a call to operator delete.
Build a call to operator delete .
/* In [class.free]

       If the result of the lookup is ambiguous or inaccessible, or if
       the lookup selects a placement deallocation function, the
       program is ill-formed.

       Therefore, we ask lookup_fnfields to complain about ambiguity.  */ /* Get the parameter types for the allocation function that is
	 being called.  */ /* Also the second argument.  */ /* First try it without the size argument.  */ /* Strip const and volatile from addr.  */ /* We make two tries at finding a matching `operator delete'.  On
     the first pass, we look for a one-operator (or placement)
     operator delete.  If we're not doing placement delete, then on
     the second pass we look for a two-argument delete.  */ /* Go through the `operator delete' functions looking for one
	 with a matching type.  */ /* The first argument must be "void *".  */ /* On the first pass, check the rest of the arguments.  */ /* On the second pass, look for a function with exactly two
	     arguments: "void *" and "size_t".  */ /* For "operator delete(void *, ...)" there will be
		      no second argument, but we will not get an exact
		      match above.  */ /* If we found a match, we're done.  */ /* If we have a matching function, call it.  */ /* Make sure we have the actual function, and not an
	 OVERLOAD.  */ /* If the FN is a member function, make sure that it is
	 accessible.  */ /* The placement args might not be suitable for overload
	     resolution at this point, so build the call directly.  */ /* [expr.new]

     If no unambiguous matching deallocation function can be found,
     propagating the exception does not cause the object's memory to
     be freed.  */