Пример #1
0
static void
write_ts_binfo_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
{
  unsigned i;
  tree t;

  /* Note that the number of BINFO slots has already been emitted in
     EXPR's header (see streamer_write_tree_header) because this length
     is needed to build the empty BINFO node on the reader side.  */
  FOR_EACH_VEC_ELT (tree, BINFO_BASE_BINFOS (expr), i, t)
    stream_write_tree (ob, t, ref_p);
  stream_write_tree (ob, NULL_TREE, false);

  stream_write_tree (ob, BINFO_OFFSET (expr), ref_p);
  stream_write_tree (ob, BINFO_VTABLE (expr), ref_p);
  stream_write_tree (ob, BINFO_VPTR_FIELD (expr), ref_p);

  streamer_write_uhwi (ob, VEC_length (tree, BINFO_BASE_ACCESSES (expr)));
  FOR_EACH_VEC_ELT (tree, BINFO_BASE_ACCESSES (expr), i, t)
    stream_write_tree (ob, t, ref_p);

  stream_write_tree (ob, BINFO_INHERITANCE_CHAIN (expr), ref_p);
  stream_write_tree (ob, BINFO_SUBVTT_INDEX (expr), ref_p);
  stream_write_tree (ob, BINFO_VPTR_INDEX (expr), ref_p);
}
Пример #2
0
static void
write_ts_binfo_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
{
  unsigned i;
  tree t;

  /* Note that the number of BINFO slots has already been emitted in
     EXPR's header (see streamer_write_tree_header) because this length
     is needed to build the empty BINFO node on the reader side.  */
  FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (expr), i, t)
    stream_write_tree (ob, t, ref_p);
  stream_write_tree (ob, NULL_TREE, false);

  stream_write_tree (ob, BINFO_OFFSET (expr), ref_p);
  stream_write_tree (ob, BINFO_VTABLE (expr), ref_p);
  stream_write_tree (ob, BINFO_VPTR_FIELD (expr), ref_p);

  /* The number of BINFO_BASE_ACCESSES has already been emitted in
     EXPR's bitfield section.  */
  FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (expr), i, t)
    stream_write_tree (ob, t, ref_p);

  /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
     and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
}
Пример #3
0
static void
lto_input_ts_binfo_tree_pointers (struct lto_input_block *ib,
				  struct data_in *data_in, tree expr)
{
  unsigned i;
  tree t;

  /* Note that the number of slots in EXPR was read in
     streamer_alloc_tree when instantiating EXPR.  However, the
     vector is empty so we cannot rely on vec::length to know how many
     elements to read.  So, this list is emitted as a 0-terminated
     list on the writer side.  */
  do
    {
      t = stream_read_tree (ib, data_in);
      if (t)
	BINFO_BASE_BINFOS (expr)->quick_push (t);
    }
  while (t);

  BINFO_OFFSET (expr) = stream_read_tree (ib, data_in);
  BINFO_VTABLE (expr) = stream_read_tree (ib, data_in);
  BINFO_VPTR_FIELD (expr) = stream_read_tree (ib, data_in);

  /* The vector of BINFO_BASE_ACCESSES is pre-allocated during
     unpacking the bitfield section.  */
  for (i = 0; i < vec_safe_length (BINFO_BASE_ACCESSES (expr)); i++)
    {
      tree a = stream_read_tree (ib, data_in);
      (*BINFO_BASE_ACCESSES (expr))[i] = a;
    }
  /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
     and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
}
Пример #4
0
static void
lto_input_ts_binfo_tree_pointers (struct lto_input_block *ib,
				  struct data_in *data_in, tree expr)
{
  unsigned i, len;
  tree t;

  /* Note that the number of slots in EXPR was read in
     streamer_alloc_tree when instantiating EXPR.  However, the
     vector is empty so we cannot rely on VEC_length to know how many
     elements to read.  So, this list is emitted as a 0-terminated
     list on the writer side.  */
  do
    {
      t = stream_read_tree (ib, data_in);
      if (t)
	VEC_quick_push (tree, BINFO_BASE_BINFOS (expr), t);
    }
  while (t);

  BINFO_OFFSET (expr) = stream_read_tree (ib, data_in);
  BINFO_VTABLE (expr) = stream_read_tree (ib, data_in);
  BINFO_VPTR_FIELD (expr) = stream_read_tree (ib, data_in);

  len = streamer_read_uhwi (ib);
  if (len > 0)
    {
      VEC_reserve_exact (tree, gc, BINFO_BASE_ACCESSES (expr), len);
      for (i = 0; i < len; i++)
	{
	  tree a = stream_read_tree (ib, data_in);
	  VEC_quick_push (tree, BINFO_BASE_ACCESSES (expr), a);
	}
    }

  BINFO_INHERITANCE_CHAIN (expr) = stream_read_tree (ib, data_in);
  BINFO_SUBVTT_INDEX (expr) = stream_read_tree (ib, data_in);
  BINFO_VPTR_INDEX (expr) = stream_read_tree (ib, data_in);
}
Пример #5
0
static void
sdbout_one_type (tree type)
{
  if (current_function_decl != NULL_TREE
      && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
    ; /* Don't change section amid function.  */
  else
    switch_to_section (text_section);

  switch (TREE_CODE (type))
    {
    case RECORD_TYPE:
    case UNION_TYPE:
    case QUAL_UNION_TYPE:
    case ENUMERAL_TYPE:
      type = TYPE_MAIN_VARIANT (type);
      /* Don't output a type twice.  */
      if (TREE_ASM_WRITTEN (type))
	/* James said test TREE_ASM_BEING_WRITTEN here.  */
	return;

      /* Output nothing if type is not yet defined.  */
      if (!COMPLETE_TYPE_P (type))
	return;

      TREE_ASM_WRITTEN (type) = 1;

      /* This is reputed to cause trouble with the following case,
	 but perhaps checking TYPE_SIZE above will fix it.  */

      /* Here is a testcase:

	struct foo {
	  struct badstr *bbb;
	} forwardref;

	typedef struct intermediate {
	  int aaaa;
	} intermediate_ref;

	typedef struct badstr {
	  int ccccc;
	} badtype;   */

      /* This change, which ought to make better output,
	 used to make the COFF assembler unhappy.
	 Changes involving KNOWN_TYPE_TAG may fix the problem.  */
      /* Before really doing anything, output types we want to refer to.  */
      /* Note that in version 1 the following two lines
	 are not used if forward references are in use.  */
      if (TREE_CODE (type) != ENUMERAL_TYPE)
	sdbout_field_types (type);

      /* Output a structure type.  */
      {
	int size = int_size_in_bytes (type);
	int member_scl = 0;
	tree tem;

	/* Record the type tag, but not in its permanent place just yet.  */
	sdbout_record_type_name (type);

	PUT_SDB_DEF (KNOWN_TYPE_TAG (type));

	switch (TREE_CODE (type))
	  {
	  case UNION_TYPE:
	  case QUAL_UNION_TYPE:
	    PUT_SDB_SCL (C_UNTAG);
	    PUT_SDB_TYPE (T_UNION);
	    member_scl = C_MOU;
	    break;

	  case RECORD_TYPE:
	    PUT_SDB_SCL (C_STRTAG);
	    PUT_SDB_TYPE (T_STRUCT);
	    member_scl = C_MOS;
	    break;

	  case ENUMERAL_TYPE:
	    PUT_SDB_SCL (C_ENTAG);
	    PUT_SDB_TYPE (T_ENUM);
	    member_scl = C_MOE;
	    break;

	  default:
	    break;
	  }

	PUT_SDB_SIZE (size);
	PUT_SDB_ENDEF;

	/* Print out the base class information with fields
	   named after the types they hold.  */
	/* This is only relevant to aggregate types.  TYPE_BINFO is used
	   for other purposes in an ENUMERAL_TYPE, so we must exclude that
	   case.  */
	if (TREE_CODE (type) != ENUMERAL_TYPE && TYPE_BINFO (type))
	  {
	    int i;
	    tree binfo, child;

	    for (binfo = TYPE_BINFO (type), i = 0;
		 BINFO_BASE_ITERATE (binfo, i, child); i++)
	      {
		tree child_type = BINFO_TYPE (child);
		tree child_type_name;

		if (TYPE_NAME (child_type) == 0)
		  continue;
		if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
		  child_type_name = TYPE_NAME (child_type);
		else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
		  {
		    child_type_name = DECL_NAME (TYPE_NAME (child_type));
		    if (child_type_name && template_name_p (child_type_name))
		      child_type_name
			= DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
		  }
		else
		  continue;

		PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
		PUT_SDB_INT_VAL (tree_low_cst (BINFO_OFFSET (child), 0));
		PUT_SDB_SCL (member_scl);
		sdbout_type (BINFO_TYPE (child));
		PUT_SDB_ENDEF;
	      }
	  }

	/* Output the individual fields.  */

	if (TREE_CODE (type) == ENUMERAL_TYPE)
	  {
	    for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
	      {
	        tree value = TREE_VALUE (tem);

	        if (TREE_CODE (value) == CONST_DECL)
	          value = DECL_INITIAL (value);

	        if (host_integerp (value, 0))
		  {
		    PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
		    PUT_SDB_INT_VAL (tree_low_cst (value, 0));
		    PUT_SDB_SCL (C_MOE);
		    PUT_SDB_TYPE (T_MOE);
		    PUT_SDB_ENDEF;
		  }
	      }
	  }
	else			/* record or union type */
	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
	    /* Output the name, type, position (in bits), size (in bits)
	       of each field.  */

	    /* Omit here the nameless fields that are used to skip bits.
	       Also omit fields with variable size or position.
	       Also omit non FIELD_DECL nodes that GNU C++ may put here.  */
	    if (TREE_CODE (tem) == FIELD_DECL
		&& DECL_NAME (tem)
		&& DECL_SIZE (tem)
		&& host_integerp (DECL_SIZE (tem), 1)
		&& host_integerp (bit_position (tem), 0))
	      {
		const char *name;

		name = IDENTIFIER_POINTER (DECL_NAME (tem));
		PUT_SDB_DEF (name);
		if (DECL_BIT_FIELD_TYPE (tem))
		  {
		    PUT_SDB_INT_VAL (int_bit_position (tem));
		    PUT_SDB_SCL (C_FIELD);
		    sdbout_type (DECL_BIT_FIELD_TYPE (tem));
		    PUT_SDB_SIZE (tree_low_cst (DECL_SIZE (tem), 1));
		  }
		else
		  {
		    PUT_SDB_INT_VAL (int_bit_position (tem) / BITS_PER_UNIT);
		    PUT_SDB_SCL (member_scl);
		    sdbout_type (TREE_TYPE (tem));
		  }
		PUT_SDB_ENDEF;
	      }
	/* Output end of a structure,union, or enumeral definition.  */

	PUT_SDB_PLAIN_DEF ("eos");
	PUT_SDB_INT_VAL (size);
	PUT_SDB_SCL (C_EOS);
	PUT_SDB_TAG (KNOWN_TYPE_TAG (type));
	PUT_SDB_SIZE (size);
	PUT_SDB_ENDEF;
	break;
      }

    default:
      break;
    }
}
Пример #6
0
static tree
get_pseudo_ti_init (tree type, tree var_desc)
{
  gcc_assert (at_eof);
  switch (TREE_CODE (type))
    {
    case OFFSET_TYPE:
      return ptm_initializer (var_desc, type);
    case POINTER_TYPE:
      return ptr_initializer (var_desc, type);
    case ENUMERAL_TYPE:
      return generic_initializer (var_desc, type);
      break;
    case FUNCTION_TYPE:
      return generic_initializer (var_desc, type);
      break;
    case ARRAY_TYPE:
      return generic_initializer (var_desc, type);
      break;
    case UNION_TYPE:
    case RECORD_TYPE:
      if (TYPE_PTRMEMFUNC_P (type))
	return ptm_initializer (var_desc, type);
      else if (var_desc == class_desc_type_node)
	return class_initializer (var_desc, type, NULL_TREE);
      else if (var_desc == si_class_desc_type_node)
	{
          tree base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), 0);
	  tree tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
	  tree base_inits = tree_cons (NULL_TREE, tinfo, NULL_TREE);
	  
	  return class_initializer (var_desc, type, base_inits);
	}
      else
        {
	  int hint = ((CLASSTYPE_REPEATED_BASE_P (type) << 0)
		      | (CLASSTYPE_DIAMOND_SHAPED_P (type) << 1));
	  tree binfo = TYPE_BINFO (type);
          int nbases = BINFO_N_BASE_BINFOS (binfo);
	  VEC (tree) *base_accesses = BINFO_BASE_ACCESSES (binfo);
          tree base_inits = NULL_TREE;
          int ix;
          
          /* Generate the base information initializer.  */
          for (ix = nbases; ix--;)
            {
              tree base_binfo = BINFO_BASE_BINFO (binfo, ix);
              tree base_init = NULL_TREE;
              int flags = 0;
              tree tinfo;
              tree offset;
              
              if (VEC_index (tree, base_accesses, ix) == access_public_node)
                flags |= 2;
              tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
	      if (BINFO_VIRTUAL_P (base_binfo))
		{
		   /* We store the vtable offset at which the virtual
       		      base offset can be found.  */
		  offset = BINFO_VPTR_FIELD (base_binfo);
		  offset = convert (sizetype, offset);
		  flags |= 1;
		}
	      else
		offset = BINFO_OFFSET (base_binfo);
              
              /* Combine offset and flags into one field.  */
              offset = cp_build_binary_op (LSHIFT_EXPR, offset,
					   build_int_cst (NULL_TREE, 8));
              offset = cp_build_binary_op (BIT_IOR_EXPR, offset,
					   build_int_cst (NULL_TREE, flags));
              base_init = tree_cons (NULL_TREE, offset, base_init);
              base_init = tree_cons (NULL_TREE, tinfo, base_init);
              base_init = build_constructor (NULL_TREE, base_init);
              base_inits = tree_cons (NULL_TREE, base_init, base_inits);
            }
	  base_inits = build_constructor (NULL_TREE, base_inits);
	  base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
	  /* Prepend the number of bases.  */
	  base_inits = tree_cons (NULL_TREE,
				  build_int_cst (NULL_TREE, nbases),
				  base_inits);
	  /* Prepend the hint flags.  */
	  base_inits = tree_cons (NULL_TREE,
				  build_int_cst (NULL_TREE, hint),
				  base_inits);

          return class_initializer (var_desc, type, base_inits);
        }
      break;

    default:
      return generic_initializer (var_desc, type);
    }
}
Пример #7
0
static tree
get_pseudo_ti_desc (tree type)
{
  switch (TREE_CODE (type))
    {
    case OFFSET_TYPE:
      return ptm_desc_type_node;
    case POINTER_TYPE:
      return ptr_desc_type_node;
    case ENUMERAL_TYPE:
      return enum_desc_type_node;
    case FUNCTION_TYPE:
      return func_desc_type_node;
    case ARRAY_TYPE:
      return ary_desc_type_node;
    case UNION_TYPE:
    case RECORD_TYPE:
      if (TYPE_PTRMEMFUNC_P (type))
	return ptm_desc_type_node;
      else if (!COMPLETE_TYPE_P (type))
	{
	  if (!at_eof)
	    cxx_incomplete_type_error (NULL_TREE, type);
	  return class_desc_type_node;
	}
      else if (!BINFO_N_BASE_BINFOS (TYPE_BINFO (type)))
	return class_desc_type_node;
      else
	{
	  tree binfo = TYPE_BINFO (type);
	  VEC (tree) *base_accesses = BINFO_BASE_ACCESSES (binfo);
	  tree base_binfo = BINFO_BASE_BINFO (binfo, 0);
	  int num_bases = BINFO_N_BASE_BINFOS (binfo);
	  
	  if (num_bases == 1
	      && VEC_index (tree, base_accesses, 0) == access_public_node
	      && !BINFO_VIRTUAL_P (base_binfo)
	      && integer_zerop (BINFO_OFFSET (base_binfo)))
	    /* single non-virtual public.  */
	    return si_class_desc_type_node;
	  else
	    {
	      tree var_desc;
	      tree array_domain, base_array;
	      
	      if (TREE_VEC_LENGTH (vmi_class_desc_type_node) <= num_bases)
		{
		  int ix;
		  tree extend = make_tree_vec (num_bases + 5);
		  
		  for (ix = TREE_VEC_LENGTH (vmi_class_desc_type_node); ix--;)
		    TREE_VEC_ELT (extend, ix)
		      = TREE_VEC_ELT (vmi_class_desc_type_node, ix);
		  vmi_class_desc_type_node = extend;
		}
	      var_desc = TREE_VEC_ELT (vmi_class_desc_type_node, num_bases);
	      if (var_desc)
		return var_desc;
  
	      /* Create the array of __base_class_type_info entries.
		 G++ 3.2 allocated an array that had one too many
		 entries, and then filled that extra entries with
		 zeros.  */
	      if (abi_version_at_least (2))
		array_domain = build_index_type (size_int (num_bases - 1));
	      else
		array_domain = build_index_type (size_int (num_bases));
	      base_array =
		build_array_type (base_desc_type_node, array_domain);

	      push_nested_namespace (abi_node);
	      var_desc = create_pseudo_type_info
		("__vmi_class_type_info", num_bases,
		 build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
		 build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
		 build_decl (FIELD_DECL, NULL_TREE, base_array),
		 NULL);
	      pop_nested_namespace (abi_node);

	      TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = var_desc;
	      return var_desc;
	    }
	}
    default:
      return bltn_desc_type_node;
    }
}
Пример #8
0
Файл: cvt.c Проект: Fokycnuk/gcc
static tree
cp_convert_to_pointer (tree type, tree expr, bool force)
{
  tree intype = TREE_TYPE (expr);
  enum tree_code form;
  tree rval;
  if (intype == error_mark_node)
    return error_mark_node;

  if (IS_AGGR_TYPE (intype))
    {
      intype = complete_type (intype);
      if (!COMPLETE_TYPE_P (intype))
	{
	  error ("can't convert from incomplete type `%T' to `%T'",
		    intype, type);
	  return error_mark_node;
	}

      rval = build_type_conversion (type, expr);
      if (rval)
	{
	  if (rval == error_mark_node)
	    error ("conversion of `%E' from `%T' to `%T' is ambiguous",
		      expr, intype, type);
	  return rval;
	}
    }

  /* Handle anachronistic conversions from (::*)() to cv void* or (*)().  */
  if (TREE_CODE (type) == POINTER_TYPE
      && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
	  || VOID_TYPE_P (TREE_TYPE (type))))
    {
      /* Allow an implicit this pointer for pointer to member
	 functions.  */
      if (TYPE_PTRMEMFUNC_P (intype))
	{
	  if (pedantic || warn_pmf2ptr)
	    pedwarn ("converting from `%T' to `%T'", intype, type);
	  if (TREE_CODE (expr) == PTRMEM_CST)
	    expr = build_address (PTRMEM_CST_MEMBER (expr));
	  else
	    {
	      tree decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype), 
					      0);
	      decl = build_address (decl);
	      expr = get_member_function_from_ptrfunc (&decl, expr);
	    }
	}
      else if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
	{
	  if (pedantic || warn_pmf2ptr)
	    pedwarn ("converting from `%T' to `%T'", intype, type);
	  expr = build_addr_func (expr);
	}
      if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
	return build_nop (type, expr);
      intype = TREE_TYPE (expr);
    }

  if (expr == error_mark_node)
    return error_mark_node;

  form = TREE_CODE (intype);

  if (POINTER_TYPE_P (intype))
    {
      intype = TYPE_MAIN_VARIANT (intype);

      if (TYPE_MAIN_VARIANT (type) != intype
	  && TREE_CODE (type) == POINTER_TYPE
	  && TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
	  && IS_AGGR_TYPE (TREE_TYPE (type))
	  && IS_AGGR_TYPE (TREE_TYPE (intype))
	  && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
	{
	  enum tree_code code = PLUS_EXPR;
	  tree binfo;
	  tree intype_class;
	  tree type_class;
	  bool same_p;

	  intype_class = TREE_TYPE (intype);
	  type_class = TREE_TYPE (type);

	  same_p = same_type_p (TYPE_MAIN_VARIANT (intype_class), 
				TYPE_MAIN_VARIANT (type_class));
	  binfo = NULL_TREE;
	  /* Try derived to base conversion.  */
	  if (!same_p)
	    binfo = lookup_base (intype_class, type_class, ba_check, NULL);
	  if (!same_p && !binfo)
	    {
	      /* Try base to derived conversion.  */
	      binfo = lookup_base (type_class, intype_class, ba_check, NULL);
	      code = MINUS_EXPR;
	    }
	  if (binfo == error_mark_node)
	    return error_mark_node;
	  if (binfo || same_p)
	    {
	      if (binfo)
		expr = build_base_path (code, expr, binfo, 0);
	      /* Add any qualifier conversions.  */
	      return build_nop (type, expr);
	    }
	}

      if (TYPE_PTRMEMFUNC_P (type))
	{
	  error ("cannot convert `%E' from type `%T' to type `%T'",
		    expr, intype, type);
	  return error_mark_node;
	}

      return build_nop (type, expr);
    }
  else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
    {
      tree b1; 
      tree b2;
      tree binfo;
      enum tree_code code = PLUS_EXPR;
      base_kind bk;

      b1 = TYPE_PTRMEM_CLASS_TYPE (type);
      b2 = TYPE_PTRMEM_CLASS_TYPE (intype);
      binfo = lookup_base (b1, b2, ba_check, &bk);
      if (!binfo)
	{
	  binfo = lookup_base (b2, b1, ba_check, &bk);
	  code = MINUS_EXPR;
	}
      if (binfo == error_mark_node)
	return error_mark_node;

      if (bk == bk_via_virtual)
	{
	  if (force)
	    warning ("pointer to member cast from `%T' to `%T' is via virtual base",
		     intype, type);
	  else
	    {
	      error ("pointer to member cast from `%T' to `%T' is via virtual base",
		     intype, type);
	      return error_mark_node;
	    }
	  /* This is a reinterpret cast, whose result is unspecified.
	     We choose to do nothing.  */
	  return build1 (NOP_EXPR, type, expr);
	}

      if (TREE_CODE (expr) == PTRMEM_CST)
	expr = cplus_expand_constant (expr);

      if (binfo && !integer_zerop (BINFO_OFFSET (binfo)))
	expr = size_binop (code, 
			   build_nop (sizetype, expr),
			   BINFO_OFFSET (binfo));
      return build_nop (type, expr);
    }
  else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
  else if (TYPE_PTRMEMFUNC_P (intype))
    {
      if (!warn_pmf2ptr)
	{
	  if (TREE_CODE (expr) == PTRMEM_CST)
	    return cp_convert_to_pointer (type,
					  PTRMEM_CST_MEMBER (expr),
					  force);
	  else if (TREE_CODE (expr) == OFFSET_REF)
	    {
	      tree object = TREE_OPERAND (expr, 0);
	      return get_member_function_from_ptrfunc (&object,
						       TREE_OPERAND (expr, 1));
	    }
	}
      error ("cannot convert `%E' from type `%T' to type `%T'",
		expr, intype, type);
      return error_mark_node;
    }

  if (integer_zerop (expr))
    {
      if (TYPE_PTRMEMFUNC_P (type))
	return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);

      if (TYPE_PTRMEM_P (type))
	/* A NULL pointer-to-member is represented by -1, not by
	   zero.  */
	expr = build_int_2 (-1, -1);
      else
	expr = build_int_2 (0, 0);
      TREE_TYPE (expr) = type;
      /* Fix up the representation of -1 if appropriate.  */
      force_fit_type (expr, 0);
      return expr;
    }
  else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form))
    {
      error ("invalid conversion from '%T' to '%T'", intype, type);
      return error_mark_node;
    }

  if (INTEGRAL_CODE_P (form))
    {
      if (TYPE_PRECISION (intype) == POINTER_SIZE)
	return build1 (CONVERT_EXPR, type, expr);
      expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr);
      /* Modes may be different but sizes should be the same.  */
      if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
	  != GET_MODE_SIZE (TYPE_MODE (type)))
	/* There is supposed to be some integral type
	   that is the same width as a pointer.  */
	abort ();
      return convert_to_pointer (type, expr);
    }

  if (type_unknown_p (expr))
    return instantiate_type (type, expr, tf_error | tf_warning);

  error ("cannot convert `%E' from type `%T' to type `%T'",
	    expr, intype, type);
  return error_mark_node;
}