Mercurial > hg > CbC > CbC_gcc
diff gcc/cp/class.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/cp/class.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/cp/class.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Functions related to building classes and their related objects. - Copyright (C) 1987-2017 Free Software Foundation, Inc. + Copyright (C) 1987-2018 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -133,7 +133,6 @@ static void add_implicitly_declared_members (tree, tree*, int, int); static tree fixed_type_or_null (tree, int *, int *); static tree build_simple_base_path (tree expr, tree binfo); -static tree build_vtbl_ref_1 (tree, tree); static void build_vtbl_initializer (tree, tree, tree, tree, int *, vec<constructor_elt, va_gc> **); static bool check_bitfield_decl (tree); @@ -181,8 +180,6 @@ static void initialize_vtable (tree, vec<constructor_elt, va_gc> *); static void layout_nonempty_base_or_field (record_layout_info, tree, tree, splay_tree); -static tree end_of_class (tree, int); -static bool layout_empty_base (record_layout_info, tree, tree, splay_tree); static void accumulate_vtbl_inits (tree, tree, tree, tree, tree, vec<constructor_elt, va_gc> **); static void dfs_accumulate_vtbl_inits (tree, tree, tree, tree, tree, @@ -203,7 +200,6 @@ static int check_subobject_offset (tree, tree, splay_tree); static int walk_subobject_offsets (tree, subobject_offset_fn, tree, splay_tree, tree, int); -static void record_subobject_offsets (tree, tree, splay_tree, bool); static int layout_conflict_p (tree, tree, splay_tree, int); static int splay_tree_compare_integer_csts (splay_tree_key k1, splay_tree_key k2); @@ -215,16 +211,6 @@ static tree get_vcall_index (tree, tree); static bool type_maybe_constexpr_default_constructor (tree); -/* Variables shared between class.c and call.c. */ - -int n_vtables = 0; -int n_vtable_entries = 0; -int n_vtable_searches = 0; -int n_vtable_elems = 0; -int n_convert_harshness = 0; -int n_compute_conversion_costs = 0; -int n_inner_fields_searched = 0; - /* Return a COND_EXPR that executes TRUE_STMT if this execution of the 'structor is in charge of 'structing virtual bases, or FALSE_STMT otherwise. */ @@ -288,6 +274,9 @@ probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr)); if (want_pointer) probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe)); + if (dependent_type_p (probe)) + if (tree open = currently_open_class (probe)) + probe = open; if (code == PLUS_EXPR && !SAME_BINFO_TYPE_P (BINFO_TYPE (d_binfo), probe)) @@ -380,6 +369,15 @@ goto indout; } + if (!COMPLETE_TYPE_P (probe)) + { + if (complain & tf_error) + error ("cannot convert from %qT to base class %qT because %qT is " + "incomplete", BINFO_TYPE (d_binfo), BINFO_TYPE (binfo), + BINFO_TYPE (d_binfo)); + return error_mark_node; + } + /* If we're in an NSDMI, we don't have the full constructor context yet that we need for converting to a virtual base, so just build a stub CONVERT_EXPR and expand it later in bot_replace. */ @@ -425,9 +423,9 @@ interesting to the optimizers anyway. */ && !has_empty) { - expr = cp_build_indirect_ref (expr, RO_NULL, complain); + expr = cp_build_fold_indirect_ref (expr); expr = build_simple_base_path (expr, binfo); - if (rvalue) + if (rvalue && lvalue_p (expr)) expr = move (expr); if (want_pointer) expr = build_address (expr); @@ -452,7 +450,7 @@ t = TREE_TYPE (TYPE_VFIELD (current_class_type)); t = build_pointer_type (t); v_offset = fold_convert (t, current_vtt_parm); - v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain); + v_offset = cp_build_fold_indirect_ref (v_offset); } else { @@ -465,8 +463,7 @@ if (t == NULL_TREE) t = expr; } - v_offset = build_vfield_ref (cp_build_indirect_ref (t, RO_NULL, - complain), + v_offset = build_vfield_ref (cp_build_fold_indirect_ref (t), TREE_TYPE (TREE_TYPE (expr))); } @@ -477,7 +474,7 @@ v_offset = build1 (NOP_EXPR, build_pointer_type (ptrdiff_type_node), v_offset); - v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain); + v_offset = cp_build_fold_indirect_ref (v_offset); TREE_CONSTANT (v_offset) = 1; offset = convert_to_integer (ptrdiff_type_node, @@ -516,7 +513,7 @@ indout: if (!want_pointer) { - expr = cp_build_indirect_ref (expr, RO_NULL, complain); + expr = cp_build_fold_indirect_ref (expr); if (rvalue) expr = move (expr); } @@ -552,7 +549,7 @@ in the back end. */ temp = unary_complex_lvalue (ADDR_EXPR, expr); if (temp) - expr = cp_build_indirect_ref (temp, RO_NULL, tf_warning_or_error); + expr = cp_build_fold_indirect_ref (temp); return expr; } @@ -698,8 +695,8 @@ cases for INSTANCE which we take care of here, mainly to avoid creating extra tree nodes when we don't have to. */ -static tree -build_vtbl_ref_1 (tree instance, tree idx) +tree +build_vtbl_ref (tree instance, tree idx) { tree aref; tree vtbl = NULL_TREE; @@ -729,14 +726,6 @@ return aref; } -tree -build_vtbl_ref (tree instance, tree idx) -{ - tree aref = build_vtbl_ref_1 (instance, idx); - - return aref; -} - /* Given a stable object pointer INSTANCE_PTR, return an expression which yields a function pointer corresponding to vtable element INDEX. */ @@ -745,9 +734,7 @@ { tree aref; - aref = build_vtbl_ref_1 (cp_build_indirect_ref (instance_ptr, RO_NULL, - tf_warning_or_error), - idx); + aref = build_vtbl_ref (cp_build_fold_indirect_ref (instance_ptr), idx); /* When using function descriptors, the address of the vtable entry is treated as a function pointer. */ @@ -894,12 +881,6 @@ virtuals = NULL_TREE; } - if (GATHER_STATISTICS) - { - n_vtables += 1; - n_vtable_elems += list_length (virtuals); - } - /* Initialize the association list for this type, based on our first approximation. */ BINFO_VTABLE (TYPE_BINFO (type)) = decl; @@ -1011,14 +992,11 @@ if (method == error_mark_node) return false; - /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */ - grok_special_member_properties (method); - - tree *slot = get_member_slot (type, DECL_NAME (method)); - tree current_fns = *slot; - gcc_assert (!DECL_EXTERN_C_P (method)); + tree *slot = find_member_slot (type, DECL_NAME (method)); + tree current_fns = slot ? *slot : NULL_TREE; + /* Check to see if we've already got this method. */ for (ovl_iterator iter (current_fns); iter; ++iter) { @@ -1101,7 +1079,7 @@ /* If these are versions of the same function, process and move on. */ if (TREE_CODE (fn) == FUNCTION_DECL - && maybe_version_functions (method, fn)) + && maybe_version_functions (method, fn, true)) continue; if (DECL_INHERITED_CTOR (method)) @@ -1164,8 +1142,15 @@ current_fns = ovl_insert (method, current_fns, via_using); - if (!DECL_CONV_FN_P (method) && !COMPLETE_TYPE_P (type)) - push_class_level_binding (DECL_NAME (method), current_fns); + if (!COMPLETE_TYPE_P (type) && !DECL_CONV_FN_P (method) + && !push_class_level_binding (DECL_NAME (method), current_fns)) + return false; + + if (!slot) + slot = add_member_slot (type, DECL_NAME (method)); + + /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */ + grok_special_member_properties (method); *slot = current_fns; @@ -1333,6 +1318,7 @@ /* Otherwise we're diagnosing missing tags. */ if (TREE_CODE (p->t) == FUNCTION_DECL) { + auto_diagnostic_group d; if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag " "that %qT (used in its return type) has", p->t, tag, *tp)) @@ -1340,12 +1326,14 @@ } else if (VAR_P (p->t)) { + auto_diagnostic_group d; if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag " "that %qT (used in its type) has", p->t, tag, *tp)) inform (location_of (*tp), "%qT declared here", *tp); } else if (TYPE_P (p->subob)) { + auto_diagnostic_group d; if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag " "that base %qT has", p->t, tag, p->subob)) inform (location_of (p->subob), "%qT declared here", @@ -1353,6 +1341,7 @@ } else { + auto_diagnostic_group d; if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag " "that %qT (used in the type of %qD) has", p->t, tag, *tp, p->subob)) @@ -1522,8 +1511,7 @@ TREE_VALUE (attr) = chainon (data.tags, TREE_VALUE (attr)); else DECL_ATTRIBUTES (t) - = tree_cons (get_identifier ("abi_tag"), data.tags, - DECL_ATTRIBUTES (t)); + = tree_cons (abi_tag_identifier, data.tags, DECL_ATTRIBUTES (t)); } mark_abi_tags (t, false); @@ -1595,8 +1583,7 @@ TREE_VALUE (attr) = chainon (data.tags, TREE_VALUE (attr)); else TYPE_ATTRIBUTES (t) - = tree_cons (get_identifier ("abi_tag"), data.tags, - TYPE_ATTRIBUTES (t)); + = tree_cons (abi_tag_identifier, data.tags, TYPE_ATTRIBUTES (t)); } mark_abi_tags (t, false); @@ -2039,6 +2026,7 @@ { int has_member_fn = 0; int has_nonprivate_method = 0; + bool nonprivate_ctor = false; if (!warn_ctor_dtor_privacy /* If the class has friends, those entities might create and @@ -2069,7 +2057,11 @@ non-private statics, we can't ever call any of the private member functions.) */ for (tree fn = TYPE_FIELDS (t); fn; fn = DECL_CHAIN (fn)) - if (!DECL_DECLARES_FUNCTION_P (fn)) + if (TREE_CODE (fn) == USING_DECL + && DECL_NAME (fn) == ctor_identifier + && !TREE_PRIVATE (fn)) + nonprivate_ctor = true; + else if (!DECL_DECLARES_FUNCTION_P (fn)) /* Not a function. */; else if (DECL_ARTIFICIAL (fn)) /* We're not interested in compiler-generated methods; they don't @@ -2131,7 +2123,6 @@ /* Implicitly generated constructors are always public. */ && !CLASSTYPE_LAZY_DEFAULT_CTOR (t)) { - bool nonprivate_ctor = false; tree copy_or_move = NULL_TREE; /* If a non-template class does not define a copy @@ -2450,7 +2441,7 @@ over_return = TREE_TYPE (TREE_TYPE (overrider_target)); base_return = TREE_TYPE (TREE_TYPE (target_fn)); - if (POINTER_TYPE_P (over_return) + if (INDIRECT_TYPE_P (over_return) && TREE_CODE (over_return) == TREE_CODE (base_return) && CLASS_TYPE_P (TREE_TYPE (over_return)) && CLASS_TYPE_P (TREE_TYPE (base_return)) @@ -2493,19 +2484,20 @@ order. Of course it is lame that we have to repeat the search here anyway -- we should really be caching pieces of the vtable and avoiding this repeated work. */ - tree thunk_binfo, base_binfo; + tree thunk_binfo = NULL_TREE; + tree base_binfo = TYPE_BINFO (base_return); /* Find the base binfo within the overriding function's return type. We will always find a thunk_binfo, except when the covariancy is invalid (which we will have already diagnosed). */ - for (base_binfo = TYPE_BINFO (base_return), - thunk_binfo = TYPE_BINFO (over_return); - thunk_binfo; - thunk_binfo = TREE_CHAIN (thunk_binfo)) - if (SAME_BINFO_TYPE_P (BINFO_TYPE (thunk_binfo), - BINFO_TYPE (base_binfo))) - break; + if (base_binfo) + for (thunk_binfo = TYPE_BINFO (over_return); thunk_binfo; + thunk_binfo = TREE_CHAIN (thunk_binfo)) + if (SAME_BINFO_TYPE_P (BINFO_TYPE (thunk_binfo), + BINFO_TYPE (base_binfo))) + break; + gcc_assert (thunk_binfo || errorcount); /* See if virtual inheritance is involved. */ for (virtual_offset = thunk_binfo; @@ -2883,9 +2875,7 @@ static void finish_struct_anon_r (tree field, bool complain) { - bool is_union = TREE_CODE (TREE_TYPE (field)) == UNION_TYPE; - tree elt = TYPE_FIELDS (TREE_TYPE (field)); - for (; elt; elt = DECL_CHAIN (elt)) + for (tree elt = TYPE_FIELDS (TREE_TYPE (field)); elt; elt = DECL_CHAIN (elt)) { /* We're generally only interested in entities the user declared, but we also find nested classes by noticing @@ -2899,50 +2889,38 @@ || TYPE_UNNAMED_P (TREE_TYPE (elt)))) continue; - if (TREE_CODE (elt) != FIELD_DECL) + if (complain + && (TREE_CODE (elt) != FIELD_DECL + || (TREE_PRIVATE (elt) || TREE_PROTECTED (elt)))) { /* We already complained about static data members in finish_static_data_member_decl. */ - if (complain && !VAR_P (elt)) + if (!VAR_P (elt)) { - if (is_union) - permerror (DECL_SOURCE_LOCATION (elt), - "%q#D invalid; an anonymous union can " - "only have non-static data members", elt); - else - permerror (DECL_SOURCE_LOCATION (elt), - "%q#D invalid; an anonymous struct can " - "only have non-static data members", elt); - } - continue; - } - - if (complain) - { - if (TREE_PRIVATE (elt)) - { - if (is_union) - permerror (DECL_SOURCE_LOCATION (elt), - "private member %q#D in anonymous union", elt); - else - permerror (DECL_SOURCE_LOCATION (elt), - "private member %q#D in anonymous struct", elt); - } - else if (TREE_PROTECTED (elt)) - { - if (is_union) - permerror (DECL_SOURCE_LOCATION (elt), - "protected member %q#D in anonymous union", elt); - else - permerror (DECL_SOURCE_LOCATION (elt), - "protected member %q#D in anonymous struct", elt); + auto_diagnostic_group d; + if (permerror (DECL_SOURCE_LOCATION (elt), + TREE_CODE (TREE_TYPE (field)) == UNION_TYPE + ? "%q#D invalid; an anonymous union may " + "only have public non-static data members" + : "%q#D invalid; an anonymous struct may " + "only have public non-static data members", elt)) + { + static bool hint; + if (flag_permissive && !hint) + { + hint = true; + inform (DECL_SOURCE_LOCATION (elt), + "this flexibility is deprecated and will be " + "removed"); + } + } } } TREE_PRIVATE (elt) = TREE_PRIVATE (field); TREE_PROTECTED (elt) = TREE_PROTECTED (field); - /* Recurse into the anonymous aggregates to handle correctly + /* Recurse into the anonymous aggregates to correctly handle access control (c++/24926): class A { @@ -3011,7 +2989,7 @@ dfs_declare_virt_assop_and_dtor (tree binfo, void *data) { tree bv, fn, t = (tree)data; - tree opname = cp_assignment_operator_id (NOP_EXPR); + tree opname = assign_op_identifier; gcc_assert (t && CLASS_TYPE_P (t)); gcc_assert (binfo && TREE_CODE (binfo) == TREE_BINFO); @@ -3076,7 +3054,7 @@ if (nparms == 0) return; if (nparms == 1 - && TREE_CODE (parms[0]) == REFERENCE_TYPE) + && TYPE_REF_P (parms[0])) { tree parm = TYPE_MAIN_VARIANT (TREE_TYPE (parms[0])); if (parm == t || parm == DECL_CONTEXT (ctor)) @@ -3124,6 +3102,7 @@ one_inheriting_sig (t, ctor, new_parms, i); if (parms == NULL_TREE) { + auto_diagnostic_group d; if (warning (OPT_Winherited_variadic_ctor, "the ellipsis in %qD is not inherited", ctor)) inform (DECL_SOURCE_LOCATION (ctor), "%qD declared here", ctor); @@ -3278,12 +3257,14 @@ && tree_int_cst_lt (TYPE_SIZE (type), w))) warning_at (DECL_SOURCE_LOCATION (field), 0, "width of %qD exceeds its type", field); - else if (TREE_CODE (type) == ENUMERAL_TYPE - && (0 > (compare_tree_int - (w, TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type)))))) - warning_at (DECL_SOURCE_LOCATION (field), 0, - "%qD is too small to hold all values of %q#T", - field, type); + else if (TREE_CODE (type) == ENUMERAL_TYPE) + { + int prec = TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type)); + if (compare_tree_int (w, prec) < 0) + warning_at (DECL_SOURCE_LOCATION (field), 0, + "%qD is too small to hold all values of %q#T", + field, type); + } } if (w != error_mark_node) @@ -3483,7 +3464,7 @@ "a member of a union", x); continue; } - if (TREE_CODE (type) == REFERENCE_TYPE + if (TYPE_REF_P (type) && TREE_CODE (x) == FIELD_DECL) { error ("non-static data member %q+D in a union may not " @@ -3537,7 +3518,7 @@ CLASSTYPE_NON_STD_LAYOUT (t) = 1; /* If this is of reference type, check if it needs an init. */ - if (TREE_CODE (type) == REFERENCE_TYPE) + if (TYPE_REF_P (type)) { CLASSTYPE_NON_LAYOUT_POD_P (t) = 1; CLASSTYPE_NON_STD_LAYOUT (t) = 1; @@ -3615,7 +3596,7 @@ "and %<mutable%>", x); continue; } - if (TREE_CODE (type) == REFERENCE_TYPE) + if (TYPE_REF_P (type)) { error ("member %q+D cannot be declared as a %<mutable%> " "reference", x); @@ -3976,20 +3957,52 @@ return 0; } -/* Record all of the empty subobjects of TYPE (either a type or a - binfo). If IS_DATA_MEMBER is true, then a non-static data member - is being placed at OFFSET; otherwise, it is a base class that is - being placed at OFFSET. */ +/* Return true iff FIELD_DECL DECL is potentially overlapping. */ + +static bool +field_poverlapping_p (tree decl) +{ + /* Base fields are actually potentially overlapping, but C++ bases go through + a different code path based on binfos, and ObjC++ base fields are laid out + in objc-act, so we don't want layout_class_type to mess with them. */ + if (DECL_FIELD_IS_BASE (decl)) + { + gcc_checking_assert (c_dialect_objc ()); + return false; + } + + return lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (decl)); +} + +/* Record all of the empty subobjects of DECL_OR_BINFO. */ static void -record_subobject_offsets (tree type, - tree offset, - splay_tree offsets, - bool is_data_member) -{ +record_subobject_offsets (tree decl_or_binfo, + splay_tree offsets) +{ + tree type, offset; + bool overlapping, vbases_p; + + if (DECL_P (decl_or_binfo)) + { + tree decl = decl_or_binfo; + type = TREE_TYPE (decl); + offset = byte_position (decl); + overlapping = field_poverlapping_p (decl); + vbases_p = true; + } + else + { + type = BINFO_TYPE (decl_or_binfo); + offset = BINFO_OFFSET (decl_or_binfo); + overlapping = true; + vbases_p = false; + } + tree max_offset; /* If recording subobjects for a non-static data member or a - non-empty base class , we do not need to record offsets beyond + non-empty base class, we do not need to record offsets beyond the size of the biggest empty class. Additional data members will go at the end of the class. Additional base classes will go either at offset zero (if empty, in which case they cannot @@ -4001,13 +4014,13 @@ other empty classes might later be placed) or at the end of the class (where other objects might then be placed, so other empty subobjects might later overlap). */ - if (is_data_member - || !is_empty_class (BINFO_TYPE (type))) + if (!overlapping + || !is_empty_class (type)) max_offset = sizeof_biggest_empty_class; else max_offset = NULL_TREE; walk_subobject_offsets (type, record_subobject_offset, offset, - offsets, max_offset, is_data_member); + offsets, max_offset, vbases_p); } /* Returns nonzero if any of the empty subobjects of TYPE (located at @@ -4167,55 +4180,80 @@ type. Return nonzero iff we added it at the end. */ static bool -layout_empty_base (record_layout_info rli, tree binfo, - tree eoc, splay_tree offsets) +layout_empty_base_or_field (record_layout_info rli, tree binfo_or_decl, + splay_tree offsets) { tree alignment; - tree basetype = BINFO_TYPE (binfo); bool atend = false; + tree binfo = NULL_TREE; + tree decl = NULL_TREE; + tree type; + if (TREE_CODE (binfo_or_decl) == TREE_BINFO) + { + binfo = binfo_or_decl; + type = BINFO_TYPE (binfo); + } + else + { + decl = binfo_or_decl; + type = TREE_TYPE (decl); + } + + /* On some platforms (ARM), even empty classes will not be + byte-aligned. */ + tree eoc = round_up_loc (input_location, + rli_size_unit_so_far (rli), + CLASSTYPE_ALIGN_UNIT (type)); /* This routine should only be used for empty classes. */ - gcc_assert (is_empty_class (basetype)); - alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype)); - - if (!integer_zerop (BINFO_OFFSET (binfo))) - propagate_binfo_offsets - (binfo, size_diffop_loc (input_location, - size_zero_node, BINFO_OFFSET (binfo))); + gcc_assert (is_empty_class (type)); + alignment = size_int (CLASSTYPE_ALIGN_UNIT (type)); /* This is an empty base class. We first try to put it at offset zero. */ - if (layout_conflict_p (binfo, - BINFO_OFFSET (binfo), + tree offset = size_zero_node; + if (layout_conflict_p (type, + offset, offsets, /*vbases_p=*/0)) { /* That didn't work. Now, we move forward from the next available spot in the class. */ atend = true; - propagate_binfo_offsets (binfo, fold_convert (ssizetype, eoc)); + offset = eoc; while (1) { - if (!layout_conflict_p (binfo, - BINFO_OFFSET (binfo), + if (!layout_conflict_p (type, + offset, offsets, /*vbases_p=*/0)) /* We finally found a spot where there's no overlap. */ break; /* There's overlap here, too. Bump along to the next spot. */ - propagate_binfo_offsets (binfo, alignment); - } - } - - if (CLASSTYPE_USER_ALIGN (basetype)) - { - rli->record_align = MAX (rli->record_align, CLASSTYPE_ALIGN (basetype)); + offset = size_binop (PLUS_EXPR, offset, alignment); + } + } + + if (CLASSTYPE_USER_ALIGN (type)) + { + rli->record_align = MAX (rli->record_align, CLASSTYPE_ALIGN (type)); if (warn_packed) - rli->unpacked_align = MAX (rli->unpacked_align, CLASSTYPE_ALIGN (basetype)); + rli->unpacked_align = MAX (rli->unpacked_align, CLASSTYPE_ALIGN (type)); TYPE_USER_ALIGN (rli->t) = 1; } + if (binfo) + /* Adjust BINFO_OFFSET (binfo) to be exactly OFFSET. */ + propagate_binfo_offsets (binfo, + size_diffop (offset, BINFO_OFFSET (binfo))); + else + { + DECL_FIELD_OFFSET (decl) = offset; + DECL_FIELD_BIT_OFFSET (decl) = bitsize_zero_node; + SET_DECL_OFFSET_ALIGN (decl, BITS_PER_UNIT); + } + return atend; } @@ -4232,8 +4270,14 @@ DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_FIELD_CONTEXT (decl) = t; - DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype); - DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype); + if (is_empty_class (basetype)) + /* CLASSTYPE_SIZE is one byte, but the field needs to have size zero. */ + DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = size_zero_node; + else + { + DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype); + DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype); + } SET_DECL_ALIGN (decl, CLASSTYPE_ALIGN (basetype)); DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype); SET_DECL_MODE (decl, TYPE_MODE (basetype)); @@ -4287,15 +4331,7 @@ } else { - tree eoc; - bool atend; - - /* On some platforms (ARM), even empty classes will not be - byte-aligned. */ - eoc = round_up_loc (input_location, - rli_size_unit_so_far (rli), - CLASSTYPE_ALIGN_UNIT (basetype)); - atend = layout_empty_base (rli, binfo, eoc, offsets); + bool atend = layout_empty_base_or_field (rli, binfo, offsets); /* A nearly-empty class "has no proper base class that is empty, not morally virtual, and at an offset other than zero." */ if (!BINFO_VIRTUAL_P (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t)) @@ -4333,10 +4369,7 @@ } /* Record the offsets of BINFO and its base subobjects. */ - record_subobject_offsets (binfo, - BINFO_OFFSET (binfo), - offsets, - /*is_data_member=*/false); + record_subobject_offsets (binfo, offsets); return next_field; } @@ -4483,13 +4516,8 @@ type. */ if (DECL_HAS_IN_CHARGE_PARM_P (clone)) { - tree basetype; - tree parmtypes; - tree exceptions; - - exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone)); - basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone)); - parmtypes = TYPE_ARG_TYPES (TREE_TYPE (clone)); + tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone)); + tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (clone)); /* Skip the `this' parameter. */ parmtypes = TREE_CHAIN (parmtypes); /* Skip the in-charge parameter. */ @@ -4508,12 +4536,11 @@ = build_method_type_directly (basetype, TREE_TYPE (TREE_TYPE (clone)), parmtypes); - if (exceptions) - TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), - exceptions); TREE_TYPE (clone) = cp_build_type_attribute_variant (TREE_TYPE (clone), TYPE_ATTRIBUTES (TREE_TYPE (fn))); + TREE_TYPE (clone) + = cxx_copy_lang_qualifiers (TREE_TYPE (clone), TREE_TYPE (fn)); } /* Copy the function parameters. */ @@ -4701,11 +4728,6 @@ { /* A default parameter has been added. Adjust the clone's parameters. */ - tree exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone)); - tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (clone)); - tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone)); - tree type; - clone_parms = orig_decl_parms; if (DECL_HAS_VTT_PARM_P (clone)) @@ -4715,13 +4737,15 @@ clone_parms); TREE_TYPE (clone_parms) = TREE_TYPE (orig_clone_parms); } - type = build_method_type_directly (basetype, - TREE_TYPE (TREE_TYPE (clone)), - clone_parms); - if (exceptions) - type = build_exception_variant (type, exceptions); - if (attrs) + + tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone)); + tree type + = build_method_type_directly (basetype, + TREE_TYPE (TREE_TYPE (clone)), + clone_parms); + if (tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (clone))) type = cp_build_type_attribute_variant (type, attrs); + type = cxx_copy_lang_qualifiers (type, TREE_TYPE (clone)); TREE_TYPE (clone) = type; clone_parms = NULL_TREE; @@ -4907,7 +4931,7 @@ && sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (fn))); } -/* Returns true iff class T has a user-defined constructor that can be called +/* Returns true iff class T has a user-provided constructor that can be called with more than zero arguments. */ bool @@ -4919,7 +4943,7 @@ for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter) { tree fn = *iter; - if (!DECL_ARTIFICIAL (fn) + if (user_provided_p (fn) && (TREE_CODE (fn) == TEMPLATE_DECL || (skip_artificial_parms_for (fn, DECL_ARGUMENTS (fn)) != NULL_TREE))) @@ -5038,9 +5062,9 @@ /* Does the type itself have a user-provided move assignment operator? */ if (!CLASSTYPE_LAZY_MOVE_ASSIGN (type)) for (ovl_iterator iter (get_class_binding_direct - (type, cp_assignment_operator_id (NOP_EXPR))); + (type, assign_op_identifier)); iter; ++iter) - if (!DECL_ARTIFICIAL (*iter) && move_fn_p (*iter)) + if (user_provided_p (*iter) && move_fn_p (*iter)) return true; /* Do any of its bases? */ @@ -5186,7 +5210,7 @@ if (!CLASSTYPE_LAZY_MOVE_ASSIGN (t)) for (ovl_iterator iter (get_class_binding_direct - (t, cp_assignment_operator_id (NOP_EXPR))); + (t, assign_op_identifier)); iter; ++iter) if ((!user_p || !DECL_ARTIFICIAL (*iter)) && move_fn_p (*iter)) return true; @@ -5194,6 +5218,53 @@ return false; } +/* True iff T has a move constructor that is not deleted. */ + +bool +classtype_has_non_deleted_move_ctor (tree t) +{ + if (CLASSTYPE_LAZY_MOVE_CTOR (t)) + lazily_declare_fn (sfk_move_constructor, t); + for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter) + if (move_fn_p (*iter) && !DECL_DELETED_FN (*iter)) + return true; + return false; +} + +/* If T, a class, has a user-provided copy constructor, copy assignment + operator, or destructor, returns that function. Otherwise, null. */ + +tree +classtype_has_user_copy_or_dtor (tree t) +{ + if (!CLASSTYPE_LAZY_COPY_CTOR (t)) + for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter) + { + tree fn = *iter; + if (user_provided_p (fn) && copy_fn_p (fn)) + return fn; + } + + if (!CLASSTYPE_LAZY_COPY_ASSIGN (t)) + for (ovl_iterator iter (get_class_binding_direct + (t, assign_op_identifier)); + iter; ++iter) + { + tree fn = *iter; + if (user_provided_p (fn) && copy_fn_p (fn)) + return fn; + } + + if (!CLASSTYPE_LAZY_DESTRUCTOR (t)) + { + tree fn = CLASSTYPE_DESTRUCTOR (t); + if (user_provided_p (fn)) + return fn; + } + + return NULL_TREE; +} + /* Nonzero if we need to build up a constructor call when initializing an object of this class, either because it has a user-declared constructor or because it doesn't have a default constructor (so we need to give an @@ -5224,6 +5295,7 @@ { tree fn = *iter; if (!DECL_ARTIFICIAL (fn) + || TREE_DEPRECATED (fn) || DECL_DELETED_FN (fn)) return true; } @@ -5251,6 +5323,7 @@ { tree fn = *iter; if (!DECL_ARTIFICIAL (fn) + || TREE_DEPRECATED (fn) || DECL_DELETED_FN (fn)) return true; } @@ -5304,7 +5377,7 @@ the array to the deallocation function, so we will need to store a cookie. */ fns = lookup_fnfields (TYPE_BINFO (type), - cp_operator_id (VEC_DELETE_EXPR), + ovl_op_identifier (false, VEC_DELETE_EXPR), /*protect=*/0); /* If there are no `operator []' members, or the lookup is ambiguous, then we don't need a cookie. */ @@ -5368,11 +5441,14 @@ && !DECL_CONSTRUCTOR_P (fn)) { DECL_DECLARED_CONSTEXPR_P (fn) = false; - if (!DECL_GENERATED_P (fn) - && pedwarn (DECL_SOURCE_LOCATION (fn), OPT_Wpedantic, - "enclosing class of constexpr non-static member " - "function %q+#D is not a literal type", fn)) - explain_non_literal_class (t); + if (!DECL_GENERATED_P (fn)) + { + auto_diagnostic_group d; + if (pedwarn (DECL_SOURCE_LOCATION (fn), OPT_Wpedantic, + "enclosing class of %<constexpr%> non-static " + "member function %q+#D is not a literal type", fn)) + explain_non_literal_class (t); + } } } @@ -5394,19 +5470,22 @@ /* Already explained. */ return; - inform (0, "%q+T is not literal because:", t); + auto_diagnostic_group d; + inform (UNKNOWN_LOCATION, "%q+T is not literal because:", t); if (cxx_dialect < cxx17 && LAMBDA_TYPE_P (t)) - inform (0, " %qT is a closure type, which is only literal in " + inform (UNKNOWN_LOCATION, + " %qT is a closure type, which is only literal in " "C++17 and later", t); else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)) - inform (0, " %q+T has a non-trivial destructor", t); + inform (UNKNOWN_LOCATION, " %q+T has a non-trivial destructor", t); else if (CLASSTYPE_NON_AGGREGATE (t) && !TYPE_HAS_TRIVIAL_DFLT (t) && !LAMBDA_TYPE_P (t) && !TYPE_HAS_CONSTEXPR_CTOR (t)) { - inform (0, " %q+T is not an aggregate, does not have a trivial " - "default constructor, and has no constexpr constructor that " + inform (UNKNOWN_LOCATION, + " %q+T is not an aggregate, does not have a trivial " + "default constructor, and has no %<constexpr%> constructor that " "is not a copy or move constructor", t); if (type_has_non_user_provided_default_constructor (t)) /* Note that we can't simply call locate_ctor because when the @@ -5437,7 +5516,8 @@ tree basetype = TREE_TYPE (base_binfo); if (!CLASSTYPE_LITERAL_P (basetype)) { - inform (0, " base class %qT of %q+T is non-literal", + inform (UNKNOWN_LOCATION, + " base class %qT of %q+T is non-literal", basetype, t); explain_non_literal_class (basetype); return; @@ -5540,7 +5620,9 @@ Again, other conditions for being an aggregate are checked elsewhere. */ CLASSTYPE_NON_AGGREGATE (t) - |= (type_has_user_provided_or_explicit_constructor (t) + |= ((cxx_dialect < cxx2a + ? type_has_user_provided_or_explicit_constructor (t) + : TYPE_HAS_USER_CONSTRUCTOR (t)) || TYPE_POLYMORPHIC_P (t)); /* This is the C++98/03 definition of POD; it changed in C++0x, but we retain the old definition internally for ABI reasons. */ @@ -5605,7 +5687,7 @@ continue; type = TREE_TYPE (field); - if (TREE_CODE (type) == REFERENCE_TYPE) + if (TYPE_REF_P (type)) warning_at (DECL_SOURCE_LOCATION (field), OPT_Wuninitialized, "non-static reference %q#D " "in class without a constructor", field); @@ -5640,9 +5722,9 @@ if (fn_const_p && !imp_const_p) /* If the function is defaulted outside the class, we just - give the synthesis error. */ - error ("%q+D declared to take const reference, but implicit " - "declaration would take non-const", fn); + give the synthesis error. Core Issue #1331 says this is + no longer ill-formed, it is defined as deleted instead. */ + DECL_DELETED_FN (fn) = true; } defaulted_late_check (fn); } @@ -5847,10 +5929,11 @@ /* Returns the offset of the byte just past the end of the base class with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, then - only non-virtual bases are included. */ + only non-virtual bases are included. If INCLUDE_FIELDS_P is true, + then also consider non-static data members. */ static tree -end_of_class (tree t, int include_virtuals_p) +end_of_class (tree t, bool include_virtuals_p, bool include_fields_p = false) { tree result = size_zero_node; vec<tree, va_gc> *vbases; @@ -5873,6 +5956,16 @@ result = offset; } + if (include_fields_p) + for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL) + { + offset = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (field), + DECL_SIZE_UNIT (field)); + if (tree_int_cst_lt (result, offset)) + result = offset; + } + if (include_virtuals_p) for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0; vec_safe_iterate (vbases, i, &base_binfo); i++) @@ -6059,6 +6152,27 @@ padding = NULL_TREE; + bool might_overlap = field_poverlapping_p (field); + + if (might_overlap && CLASS_TYPE_P (type) + && CLASSTYPE_NON_LAYOUT_POD_P (type)) + { + /* if D is a potentially-overlapping data member, update sizeof(C) to + max (sizeof(C), offset(D)+max (nvsize(D), dsize(D))). */ + tree nvsize = CLASSTYPE_SIZE_UNIT (type); + tree dsize = end_of_class (type, /*vbases*/true, /*fields*/true); + if (tree_int_cst_le (dsize, nvsize)) + { + DECL_SIZE_UNIT (field) = nvsize; + DECL_SIZE (field) = CLASSTYPE_SIZE (type); + } + else + { + DECL_SIZE_UNIT (field) = dsize; + DECL_SIZE (field) = bit_from_pos (dsize, bitsize_zero_node); + } + } + /* If this field is a bit-field whose width is greater than its type, then there are some special rules for allocating it. */ @@ -6125,15 +6239,14 @@ /* We must also reset the DECL_MODE of the field. */ SET_DECL_MODE (field, TYPE_MODE (type)); } + else if (might_overlap && is_empty_class (type)) + layout_empty_base_or_field (rli, field, empty_base_offsets); else layout_nonempty_base_or_field (rli, field, NULL_TREE, empty_base_offsets); /* Remember the location of any empty classes in FIELD. */ - record_subobject_offsets (TREE_TYPE (field), - byte_position(field), - empty_base_offsets, - /*is_data_member=*/true); + record_subobject_offsets (field, empty_base_offsets); /* If a bit-field does not immediately follow another bit-field, and yet it starts in the middle of a byte, we have failed to @@ -6195,6 +6308,7 @@ DECL_CONTEXT (padding_field) = t; DECL_ARTIFICIAL (padding_field) = 1; DECL_IGNORED_P (padding_field) = 1; + DECL_PADDING_P (padding_field) = 1; layout_nonempty_base_or_field (rli, padding_field, NULL_TREE, empty_base_offsets); @@ -6245,6 +6359,7 @@ bitsize_int (BITS_PER_UNIT))); SET_TYPE_ALIGN (base_t, rli->record_align); TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t); + TYPE_TYPELESS_STORAGE (base_t) = TYPE_TYPELESS_STORAGE (t); /* Copy the non-static data members of T. This will include its direct non-virtual bases & vtable. */ @@ -6464,8 +6579,7 @@ members if it hasn't been yet. */ tree eltype = fldtype; while (TREE_CODE (eltype) == ARRAY_TYPE - || TREE_CODE (eltype) == POINTER_TYPE - || TREE_CODE (eltype) == REFERENCE_TYPE) + || INDIRECT_TYPE_P (eltype)) eltype = TREE_TYPE (eltype); if (RECORD_OR_UNION_TYPE_P (eltype)) @@ -6562,14 +6676,17 @@ /* Flexible array members have no upper bound. */ if (fmem->array) { - /* Replace the zero-length array if it's been stored and - reset the after pointer. */ if (TYPE_DOMAIN (TREE_TYPE (fmem->array))) { + /* Replace the zero-length array if it's been stored and + reset the after pointer. */ fmem->after[bool (pun)] = NULL_TREE; fmem->array = fld; fmem->enclosing = pstr; } + else if (!fmem->after[bool (pun)]) + /* Make a record of another flexible array member. */ + fmem->after[bool (pun)] = fld; } else { @@ -6586,17 +6703,20 @@ static void diagnose_invalid_flexarray (const flexmems_t *fmem) { - if (fmem->array && fmem->enclosing - && pedwarn (location_of (fmem->enclosing), OPT_Wpedantic, - TYPE_DOMAIN (TREE_TYPE (fmem->array)) - ? G_("invalid use of %q#T with a zero-size array " - "in %q#D") - : G_("invalid use of %q#T with a flexible array member " - "in %q#T"), - DECL_CONTEXT (fmem->array), - DECL_CONTEXT (fmem->enclosing))) - inform (DECL_SOURCE_LOCATION (fmem->array), - "array member %q#D declared here", fmem->array); + if (fmem->array && fmem->enclosing) + { + auto_diagnostic_group d; + if (pedwarn (location_of (fmem->enclosing), OPT_Wpedantic, + TYPE_DOMAIN (TREE_TYPE (fmem->array)) + ? G_("invalid use of %q#T with a zero-size array " + "in %q#D") + : G_("invalid use of %q#T with a flexible array member " + "in %q#T"), + DECL_CONTEXT (fmem->array), + DECL_CONTEXT (fmem->enclosing))) + inform (DECL_SOURCE_LOCATION (fmem->array), + "array member %q#D declared here", fmem->array); + } } /* Issue diagnostics for invalid flexible array members or zero-length @@ -6631,6 +6751,7 @@ { location_t loc = DECL_SOURCE_LOCATION (fmem->array); + auto_diagnostic_group d; if (pedwarn (loc, OPT_Wpedantic, msg, fmem->array, t)) { inform (location_of (t), "in the definition of %q#T", t); @@ -6650,6 +6771,7 @@ location_t loc = DECL_SOURCE_LOCATION (fmem->array); diagd = true; + auto_diagnostic_group d; error_at (loc, msg, fmem->array, t); /* In the unlikely event that the member following the flexible @@ -7071,12 +7193,12 @@ /* People keep complaining that the compiler crashes on an invalid definition of initializer_list, so I guess we should explicitly reject it. What the compiler internals care about is that it's a - template and has a pointer field followed by an integer field. */ + template and has a pointer field followed by size_type field. */ bool ok = false; if (processing_template_decl) { tree f = next_initializable_field (TYPE_FIELDS (t)); - if (f && TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE) + if (f && TYPE_PTR_P (TREE_TYPE (f))) { f = next_initializable_field (DECL_CHAIN (f)); if (f && same_type_p (TREE_TYPE (f), size_type_node)) @@ -7084,9 +7206,8 @@ } } if (!ok) - fatal_error (input_location, - "definition of std::initializer_list does not match " - "#include <initializer_list>"); + fatal_error (input_location, "definition of %qD does not match " + "%<#include <initializer_list>%>", TYPE_NAME (t)); } input_location = saved_loc; @@ -7125,14 +7246,15 @@ switch (TREE_CODE (instance)) { case INDIRECT_REF: - if (POINTER_TYPE_P (TREE_TYPE (instance))) + if (INDIRECT_TYPE_P (TREE_TYPE (instance))) return NULL_TREE; else return RECUR (TREE_OPERAND (instance, 0)); case CALL_EXPR: /* This is a call to a constructor, hence it's never zero. */ - if (TREE_HAS_CONSTRUCTOR (instance)) + if (CALL_EXPR_FN (instance) + && TREE_HAS_CONSTRUCTOR (instance)) { if (nonnull) *nonnull = 1; @@ -7221,7 +7343,7 @@ return TREE_TYPE (TREE_TYPE (instance)); } } - else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) + else if (TYPE_REF_P (TREE_TYPE (instance))) { /* We only need one hash table because it is always left empty. */ if (!fixed_type_or_null_ref_ht) @@ -7294,7 +7416,7 @@ fixed = fixed_type_or_null (instance, nonnull, &cdtorp); if (fixed == NULL_TREE) return 0; - if (POINTER_TYPE_P (t)) + if (INDIRECT_TYPE_P (t)) t = TREE_TYPE (t); if (!same_type_ignoring_top_level_qualifiers_p (t, fixed)) return 0; @@ -7443,8 +7565,8 @@ --current_class_stack[current_class_depth - 1].hidden; } -/* Returns 1 if the class type currently being defined is either T or - a nested type of T. Returns the type from the current_class_stack, +/* If the class type currently being defined is either T or + a nested type of T, returns the type from the current_class_stack, which might be equivalent to but not equal to T in case of constrained partial specializations. */ @@ -7780,7 +7902,7 @@ instantiation = fn_type_unification (fn, explicit_targs, targs, args, nargs, ret, DEDUCE_EXACT, LOOKUP_NORMAL, - false, false); + NULL, false, false); if (instantiation == error_mark_node) /* Instantiation failed. */ continue; @@ -7883,10 +8005,12 @@ if (!(complain & tf_error)) return error_mark_node; - permerror (input_location, "assuming pointer to member %qD", fn); - if (!explained) - { - inform (input_location, "(a pointer to member can only be formed with %<&%E%>)", fn); + auto_diagnostic_group d; + if (permerror (input_location, "assuming pointer to member %qD", fn) + && !explained) + { + inform (input_location, "(a pointer to member can only be " + "formed with %<&%E%>)", fn); explained = 1; } } @@ -7987,6 +8111,11 @@ } } + /* If we instantiate a template, and it is a A ?: C expression + with omitted B, look through the SAVE_EXPR. */ + if (TREE_CODE (rhs) == SAVE_EXPR) + rhs = TREE_OPERAND (rhs, 0); + if (BASELINK_P (rhs)) { access_path = BASELINK_ACCESS_BINFO (rhs); @@ -8002,11 +8131,6 @@ return error_mark_node; } - /* If we instantiate a template, and it is a A ?: C expression - with omitted B, look through the SAVE_EXPR. */ - if (TREE_CODE (rhs) == SAVE_EXPR) - rhs = TREE_OPERAND (rhs, 0); - /* There are only a few kinds of expressions that may have a type dependent on overload resolution. */ gcc_assert (TREE_CODE (rhs) == ADDR_EXPR @@ -8111,23 +8235,6 @@ return get_identifier (buf); } -void -print_class_statistics (void) -{ - if (! GATHER_STATISTICS) - return; - - fprintf (stderr, "convert_harshness = %d\n", n_convert_harshness); - fprintf (stderr, "compute_conversion_costs = %d\n", n_compute_conversion_costs); - if (n_vtables) - { - fprintf (stderr, "vtables = %d; vtable searches = %d\n", - n_vtables, n_vtable_searches); - fprintf (stderr, "vtable entries = %d; vtable elems = %d\n", - n_vtable_entries, n_vtable_elems); - } -} - /* Build a dummy reference to ourselves so Derived::Base (and A::A) works, according to [class]: The class-name is also inserted @@ -8195,7 +8302,7 @@ if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field) /* An unnamed bit-field is not a data member. */ - && (DECL_NAME (field) || !DECL_C_BIT_FIELD (field)) + && !DECL_UNNAMED_BIT_FIELD (field) && !is_really_empty_class (TREE_TYPE (field))) return false; return true; @@ -8265,10 +8372,12 @@ A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. */ - permerror (input_location, "declaration of %q#D", decl); - permerror (location_of ((tree) n->value), - "changes meaning of %qD from %q#D", - OVL_NAME (decl), (tree) n->value); + if (permerror (location_of (decl), + "declaration of %q#D changes meaning of %qD", + decl, OVL_NAME (decl))) + inform (location_of ((tree) n->value), + "%qD declared here as %q#D", + OVL_NAME (decl), (tree) n->value); } } @@ -9231,6 +9340,7 @@ tree vcall_index; tree fn, fn_original; tree init = NULL_TREE; + tree idx = size_int (jx++); fn = BV_FN (v); fn_original = fn; @@ -9334,7 +9444,7 @@ int i; if (init == size_zero_node) for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i) - CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, init); + CONSTRUCTOR_APPEND_ELT (*inits, idx, init); else for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i) { @@ -9342,11 +9452,11 @@ fn, build_int_cst (NULL_TREE, i)); TREE_CONSTANT (fdesc) = 1; - CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, fdesc); + CONSTRUCTOR_APPEND_ELT (*inits, idx, fdesc); } } else - CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, init); + CONSTRUCTOR_APPEND_ELT (*inits, idx, init); } }