aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r--gcc/cp/class.c309
1 files changed, 232 insertions, 77 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 06d09681e6f..0c5ace708f2 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -127,8 +127,9 @@ static int field_decl_cmp PARAMS ((const tree *, const tree *));
static int method_name_cmp PARAMS ((const tree *, const tree *));
static void add_implicitly_declared_members PARAMS ((tree, int, int, int));
static tree fixed_type_or_null PARAMS ((tree, int *, int *));
-static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
- int, int, tree));
+static tree resolve_address_of_overloaded_function PARAMS ((tree, tree,
+ tsubst_flags_t,
+ int, int, tree));
static tree build_vtable_entry_ref PARAMS ((tree, tree, tree));
static tree build_vtbl_ref_1 PARAMS ((tree, tree));
static tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *));
@@ -288,13 +289,15 @@ build_base_path (code, expr, binfo, nonnull)
return error_mark_node;
}
+ if (!want_pointer)
+ /* This must happen before the call to save_expr. */
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
if (fixed_type_p <= 0 && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
- if (!want_pointer)
- expr = build_unary_op (ADDR_EXPR, expr, 0);
- else if (!nonnull)
+ if (want_pointer && !nonnull)
null_test = build (EQ_EXPR, boolean_type_node, expr, integer_zero_node);
offset = BINFO_OFFSET (binfo);
@@ -304,8 +307,27 @@ build_base_path (code, expr, binfo, nonnull)
/* Going via virtual base V_BINFO. We need the static offset
from V_BINFO to BINFO, and the dynamic offset from D_BINFO to
V_BINFO. That offset is an entry in D_BINFO's vtable. */
- tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
- TREE_TYPE (TREE_TYPE (expr)));
+ tree v_offset;
+
+ if (fixed_type_p < 0 && in_base_initializer)
+ {
+ /* In a base member initializer, we cannot rely on
+ the vtable being set up. We have to use the vtt_parm. */
+ tree derived = v_binfo;
+
+ while (BINFO_INHERITANCE_CHAIN (derived))
+ derived = BINFO_INHERITANCE_CHAIN (derived);
+
+ v_offset = build (PLUS_EXPR, TREE_TYPE (current_vtt_parm),
+ current_vtt_parm, BINFO_VPTR_INDEX (derived));
+
+ v_offset = build1 (INDIRECT_REF,
+ TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived))),
+ v_offset);
+ }
+ else
+ v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
+ TREE_TYPE (TREE_TYPE (expr)));
v_binfo = binfo_for_vbase (BINFO_TYPE (v_binfo), BINFO_TYPE (d_binfo));
@@ -380,6 +402,33 @@ convert_to_base (tree object, tree type, bool check_access)
return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
}
+/* EXPR is an expression with class type. BASE is a base class (a
+ BINFO) of that class type. Returns EXPR, converted to the BASE
+ type. This function assumes that EXPR is the most derived class;
+ therefore virtual bases can be found at their static offsets. */
+
+tree
+convert_to_base_statically (tree expr, tree base)
+{
+ tree expr_type;
+
+ expr_type = TREE_TYPE (expr);
+ if (!same_type_p (expr_type, BINFO_TYPE (base)))
+ {
+ tree pointer_type;
+
+ pointer_type = build_pointer_type (expr_type);
+ expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
+ if (!integer_zerop (BINFO_OFFSET (base)))
+ expr = build (PLUS_EXPR, pointer_type, expr,
+ build_nop (pointer_type, BINFO_OFFSET (base)));
+ expr = build_nop (build_pointer_type (BINFO_TYPE (base)), expr);
+ expr = build1 (INDIRECT_REF, BINFO_TYPE (base), expr);
+ }
+
+ return expr;
+}
+
/* Virtual function things. */
@@ -448,7 +497,7 @@ build_vtbl_ref_1 (instance, idx)
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
- TREE_CONSTANT (aref) = 1;
+ TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx);
return aref;
}
@@ -1130,6 +1179,9 @@ handle_using_decl (using_decl, t)
tree flist = NULL_TREE;
tree old_value;
+ if (ctype == error_mark_node)
+ return;
+
binfo = lookup_base (t, ctype, ba_any, NULL);
if (! binfo)
{
@@ -1832,7 +1884,7 @@ maybe_warn_about_overly_private_class (t)
return;
has_nonprivate_method = 1;
- break;
+ /* Keep searching for a static member function. */
}
else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn))
has_member_fn = 1;
@@ -2152,7 +2204,11 @@ same_signature_p (fndecl, base_fndecl)
if (DECL_DESTRUCTOR_P (base_fndecl) || DECL_DESTRUCTOR_P (fndecl))
return 0;
- if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
+ if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl)
+ || (DECL_CONV_FN_P (fndecl)
+ && DECL_CONV_FN_P (base_fndecl)
+ && same_type_p (DECL_CONV_FN_TYPE (fndecl),
+ DECL_CONV_FN_TYPE (base_fndecl))))
{
tree types, base_types;
types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
@@ -2537,11 +2593,19 @@ get_basefndecls (name, t)
int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
int i;
- for (methods = TYPE_METHODS (t); methods; methods = TREE_CHAIN (methods))
- if (TREE_CODE (methods) == FUNCTION_DECL
- && DECL_VINDEX (methods) != NULL_TREE
- && DECL_NAME (methods) == name)
- base_fndecls = tree_cons (NULL_TREE, methods, base_fndecls);
+ /* Find virtual functions in T with the indicated NAME. */
+ i = lookup_fnfields_1 (t, name);
+ if (i != -1)
+ for (methods = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), i);
+ methods;
+ methods = OVL_NEXT (methods))
+ {
+ tree method = OVL_CURRENT (methods);
+
+ if (TREE_CODE (method) == FUNCTION_DECL
+ && DECL_VINDEX (method))
+ base_fndecls = tree_cons (NULL_TREE, method, base_fndecls);
+ }
if (base_fndecls)
return base_fndecls;
@@ -2571,7 +2635,8 @@ check_for_override (decl, ctype)
override a virtual function from a base class. */
return;
if ((DECL_DESTRUCTOR_P (decl)
- || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)))
+ || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl))
+ || DECL_CONV_FN_P (decl))
&& look_for_overrides (ctype, decl)
&& !DECL_STATIC_FUNCTION_P (decl))
/* Set DECL_VINDEX to a value that is neither an INTEGER_CST nor
@@ -3061,15 +3126,6 @@ check_field_decl (field, t, cant_have_const_ctor,
cp_error_at ("multiple fields in union `%T' initialized");
*any_default_members = 1;
}
-
- /* Non-bit-fields are aligned for their type, except packed fields
- which require only BITS_PER_UNIT alignment. */
- DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
- (DECL_PACKED (field)
- ? BITS_PER_UNIT
- : TYPE_ALIGN (TREE_TYPE (field))));
- if (! DECL_PACKED (field))
- DECL_USER_ALIGN (field) |= TYPE_USER_ALIGN (TREE_TYPE (field));
}
/* Check the data members (both static and non-static), class-scoped
@@ -3175,9 +3231,30 @@ check_field_decls (tree t, tree *access_decls,
/* If we've gotten this far, it's a data member, possibly static,
or an enumerator. */
-
DECL_CONTEXT (x) = t;
+ /* When this goes into scope, it will be a non-local reference. */
+ DECL_NONLOCAL (x) = 1;
+
+ if (TREE_CODE (t) == UNION_TYPE)
+ {
+ /* [class.union]
+
+ If a union contains a static data member, or a member of
+ reference type, the program is ill-formed. */
+ if (TREE_CODE (x) == VAR_DECL)
+ {
+ cp_error_at ("`%D' may not be static because it is a member of a union", x);
+ continue;
+ }
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ cp_error_at ("`%D' may not have reference type `%T' because it is a member of a union",
+ x, type);
+ continue;
+ }
+ }
+
/* ``A local class cannot have static data members.'' ARM 9.4 */
if (current_function_decl && TREE_STATIC (x))
cp_error_at ("field `%D' in local class cannot be static", x);
@@ -3207,21 +3284,9 @@ check_field_decls (tree t, tree *access_decls,
if (type == error_mark_node)
continue;
- /* When this goes into scope, it will be a non-local reference. */
- DECL_NONLOCAL (x) = 1;
-
- if (TREE_CODE (x) == CONST_DECL)
+ if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
continue;
- if (TREE_CODE (x) == VAR_DECL)
- {
- if (TREE_CODE (t) == UNION_TYPE)
- /* Unions cannot have static members. */
- cp_error_at ("field `%D' declared static in union", x);
-
- continue;
- }
-
/* Now it can only be a FIELD_DECL. */
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
@@ -3252,6 +3317,14 @@ check_field_decls (tree t, tree *access_decls,
if (TREE_CODE (type) == POINTER_TYPE)
has_pointers = 1;
+ if (CLASS_TYPE_P (type))
+ {
+ if (CLASSTYPE_REF_FIELDS_NEED_INIT (type))
+ SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (type))
+ SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT (t, 1);
+ }
+
if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
CLASSTYPE_HAS_MUTABLE (t) = 1;
@@ -3841,9 +3914,8 @@ build_base_field (record_layout_info rli, tree binfo,
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
- /* Tell the backend not to round up to TYPE_ALIGN. */
- DECL_PACKED (decl) = 1;
-
+ DECL_IGNORED_P (decl) = 1;
+
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
objects of the same type at the same address. */
@@ -4048,6 +4120,9 @@ build_clone (fn, name)
if (exceptions)
TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
exceptions);
+ TREE_TYPE (clone)
+ = build_type_attribute_variant (TREE_TYPE (clone),
+ TYPE_ATTRIBUTES (TREE_TYPE (fn)));
}
/* Copy the function parameters. But, DECL_ARGUMENTS on a TEMPLATE_DECL
@@ -4762,7 +4837,7 @@ end_of_class (t, include_virtuals_p)
if (!include_virtuals_p
&& TREE_VIA_VIRTUAL (binfo)
- && !BINFO_PRIMARY_P (binfo))
+ && BINFO_PRIMARY_BASE_OF (binfo) != TYPE_BINFO (t))
continue;
offset = end_of_base (binfo);
@@ -4987,12 +5062,28 @@ layout_class_type (tree t, tree *virtuals_p)
DECL_SIZE (field) = TYPE_SIZE (integer_type);
DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
DECL_USER_ALIGN (field) = TYPE_USER_ALIGN (integer_type);
+ layout_nonempty_base_or_field (rli, field, NULL_TREE,
+ empty_base_offsets);
+ /* Now that layout has been performed, set the size of the
+ field to the size of its declared type; the rest of the
+ field is effectively invisible. */
+ DECL_SIZE (field) = TYPE_SIZE (type);
+ /* We must also reset the DECL_MODE of the field. */
+ if (abi_version_at_least (2))
+ DECL_MODE (field) = TYPE_MODE (type);
+ else if (warn_abi
+ && DECL_MODE (field) != TYPE_MODE (type))
+ /* Versions of G++ before G++ 3.4 did not reset the
+ DECL_MODE. */
+ warning ("the offset of `%D' may not be ABI-compliant and may "
+ "change in a future version of GCC", field);
}
else
- padding = NULL_TREE;
-
- layout_nonempty_base_or_field (rli, field, NULL_TREE,
- empty_base_offsets);
+ {
+ padding = NULL_TREE;
+ layout_nonempty_base_or_field (rli, field, NULL_TREE,
+ empty_base_offsets);
+ }
/* Remember the location of any empty classes in FIELD. */
if (abi_version_at_least (2))
@@ -5084,16 +5175,28 @@ layout_class_type (tree t, tree *virtuals_p)
}
else
{
+ tree eoc;
+
+ /* If the ABI version is not at least two, and the last
+ field was a bit-field, RLI may not be on a byte
+ boundary. In particular, rli_size_unit_so_far might
+ indicate the last complete byte, while rli_size_so_far
+ indicates the total number of bits used. Therefore,
+ rli_size_so_far, rather than rli_size_unit_so_far, is
+ used to compute TYPE_SIZE_UNIT. */
+ eoc = end_of_class (t, /*include_virtuals_p=*/0);
TYPE_SIZE_UNIT (base_t)
= size_binop (MAX_EXPR,
- rli_size_unit_so_far (rli),
- end_of_class (t, /*include_virtuals_p=*/0));
+ convert (sizetype,
+ size_binop (CEIL_DIV_EXPR,
+ rli_size_so_far (rli),
+ bitsize_int (BITS_PER_UNIT))),
+ eoc);
TYPE_SIZE (base_t)
= size_binop (MAX_EXPR,
rli_size_so_far (rli),
size_binop (MULT_EXPR,
- convert (bitsizetype,
- TYPE_SIZE_UNIT (base_t)),
+ convert (bitsizetype, eoc),
bitsize_int (BITS_PER_UNIT)));
}
TYPE_ALIGN (base_t) = rli->record_align;
@@ -5116,6 +5219,7 @@ layout_class_type (tree t, tree *virtuals_p)
/* Record the base version of the type. */
CLASSTYPE_AS_BASE (t) = base_t;
+ TYPE_CONTEXT (base_t) = t;
}
else
CLASSTYPE_AS_BASE (t) = t;
@@ -5154,6 +5258,30 @@ layout_class_type (tree t, tree *virtuals_p)
splay_tree_delete (empty_base_offsets);
}
+/* Returns the virtual function with which the vtable for TYPE is
+ emitted, or NULL_TREE if that heuristic is not applicable to TYPE. */
+
+static tree
+key_method (tree type)
+{
+ tree method;
+
+ if (TYPE_FOR_JAVA (type)
+ || processing_template_decl
+ || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+ || CLASSTYPE_INTERFACE_KNOWN (type))
+ return NULL_TREE;
+
+ for (method = TYPE_METHODS (type); method != NULL_TREE;
+ method = TREE_CHAIN (method))
+ if (DECL_VINDEX (method) != NULL_TREE
+ && ! DECL_DECLARED_INLINE_P (method)
+ && ! DECL_PURE_VIRTUAL_P (method))
+ return method;
+
+ return NULL_TREE;
+}
+
/* Perform processing required when the definition of T (a class type)
is complete. */
@@ -5195,6 +5323,17 @@ finish_struct_1 (t)
bases and members and add implicitly generated methods. */
check_bases_and_members (t);
+ /* Find the key method */
+ if (TYPE_CONTAINS_VPTR_P (t))
+ {
+ CLASSTYPE_KEY_METHOD (t) = key_method (t);
+
+ /* If a polymorphic class has no key method, we may emit the vtable
+ in every translation unit where the class definition appears. */
+ if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)
+ keyed_classes = tree_cons (NULL_TREE, t, keyed_classes);
+ }
+
/* Layout the class itself. */
layout_class_type (t, &virtuals);
@@ -5263,9 +5402,6 @@ finish_struct_1 (t)
? TARGET_VTABLE_USES_DESCRIPTORS : 1))
if (TREE_CODE (DECL_VINDEX (BV_FN (fn))) != INTEGER_CST)
DECL_VINDEX (BV_FN (fn)) = build_shared_int_cst (vindex);
-
- /* Add this class to the list of dynamic classes. */
- dynamic_classes = tree_cons (NULL_TREE, t, dynamic_classes);
}
finish_struct_bits (t);
@@ -5347,7 +5483,6 @@ unreverse_member_declarations (t)
/* The following lists are all in reverse order. Put them in
declaration order now. */
TYPE_METHODS (t) = nreverse (TYPE_METHODS (t));
- CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (t));
CLASSTYPE_DECL_LIST (t) = nreverse (CLASSTYPE_DECL_LIST (t));
/* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
@@ -5517,11 +5652,21 @@ fixed_type_or_null (instance, nonnull, cdtorp)
/* Reference variables should be references to objects. */
if (nonnull)
*nonnull = 1;
-
- if (TREE_CODE (instance) == VAR_DECL
- && DECL_INITIAL (instance))
- return fixed_type_or_null (DECL_INITIAL (instance),
- nonnull, cdtorp);
+
+ /* DECL_VAR_MARKED_P is used to prevent recursion; a
+ variable's initializer may refer to the variable
+ itself. */
+ if (TREE_CODE (instance) == VAR_DECL
+ && DECL_INITIAL (instance)
+ && !DECL_VAR_MARKED_P (instance))
+ {
+ tree type;
+ DECL_VAR_MARKED_P (instance) = 1;
+ type = fixed_type_or_null (DECL_INITIAL (instance),
+ nonnull, cdtorp);
+ DECL_VAR_MARKED_P (instance) = 0;
+ return type;
+ }
}
return NULL_TREE;
@@ -5699,7 +5844,7 @@ pushclass (type, modify)
unuse_fields (type);
}
- storetags (CLASSTYPE_TAGS (type));
+ cxx_remember_type_decls (CLASSTYPE_NESTED_UDTS (type));
}
}
@@ -5884,13 +6029,13 @@ pop_lang_context ()
static tree
resolve_address_of_overloaded_function (target_type,
overload,
- complain,
+ flags,
ptrmem,
template_only,
explicit_targs)
tree target_type;
tree overload;
- int complain;
+ tsubst_flags_t flags;
int ptrmem;
int template_only;
tree explicit_targs;
@@ -5954,7 +6099,7 @@ resolve_address_of_overloaded_function (target_type,
}
else
{
- if (complain)
+ if (flags & tf_error)
error ("\
cannot resolve overloaded function `%D' based on conversion to type `%T'",
DECL_NAME (OVL_FUNCTION (overload)), target_type);
@@ -5983,7 +6128,11 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
/* We're looking for a non-static member, and this isn't
one, or vice versa. */
continue;
-
+
+ /* Ignore anticipated decls of undeclared builtins. */
+ if (DECL_ANTICIPATED (fn))
+ continue;
+
/* See if there's a match. */
fntype = TREE_TYPE (fn);
if (is_ptrmem)
@@ -6074,7 +6223,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
if (matches == NULL_TREE)
{
/* There were *no* matches. */
- if (complain)
+ if (flags & tf_error)
{
error ("no matches converting function `%D' to type `%#T'",
DECL_NAME (OVL_FUNCTION (overload)),
@@ -6095,7 +6244,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
{
/* There were too many matches. */
- if (complain)
+ if (flags & tf_error)
{
tree match;
@@ -6122,7 +6271,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
{
static int explained;
- if (!complain)
+ if (!(flags & tf_error))
return error_mark_node;
pedwarn ("assuming pointer to member `%D'", fn);
@@ -6132,7 +6281,13 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
explained = 1;
}
}
- mark_used (fn);
+
+ /* If we're doing overload resolution purely for the purpose of
+ determining conversion sequences, we should not consider the
+ function used. If this conversion sequence is selected, the
+ function will be marked as used at this point. */
+ if (!(flags & tf_conv))
+ mark_used (fn);
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
return build_unary_op (ADDR_EXPR, fn, 0);
@@ -6162,6 +6317,7 @@ instantiate_type (lhstype, rhs, flags)
tree lhstype, rhs;
tsubst_flags_t flags;
{
+ tsubst_flags_t flags_in = flags;
int complain = (flags & tf_error);
int strict = (flags & tf_no_attributes)
? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
@@ -6252,7 +6408,7 @@ instantiate_type (lhstype, rhs, flags)
return
resolve_address_of_overloaded_function (lhstype,
fns,
- complain,
+ flags_in,
allow_ptrmem,
/*template_only=*/1,
args);
@@ -6262,7 +6418,7 @@ instantiate_type (lhstype, rhs, flags)
return
resolve_address_of_overloaded_function (lhstype,
rhs,
- complain,
+ flags_in,
allow_ptrmem,
/*template_only=*/0,
/*explicit_targs=*/NULL_TREE);
@@ -6454,6 +6610,7 @@ build_self_reference ()
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
+ SET_DECL_SELF_REFERENCE_P (value);
if (processing_template_decl)
value = push_template_decl (value);
@@ -6567,7 +6724,7 @@ maybe_note_name_used_in_class (name, decl)
splay_tree names_used;
/* If we're not defining a class, there's nothing to do. */
- if (!current_class_type || !TYPE_BEING_DEFINED (current_class_type))
+ if (!innermost_scope_is_class_p ())
return;
/* If there's already a binding for this NAME, then we don't have
@@ -8170,22 +8327,20 @@ build_rtti_vtbl_entries (binfo, vid)
/* The second entry is the address of the typeinfo object. */
if (flag_rtti)
- decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0);
+ decl = build_address (get_tinfo_decl (t));
else
decl = integer_zero_node;
/* Convert the declaration to a type that can be stored in the
vtable. */
- init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
- TREE_CONSTANT (init) = 1;
+ init = build_nop (vfunc_ptr_type_node, decl);
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. Convert the offset to look like a
function pointer, so that we can put it in the vtable. */
- init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
- TREE_CONSTANT (init) = 1;
+ init = build_nop (vfunc_ptr_type_node, offset);
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
}