diff options
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r-- | gcc/cp/class.c | 134 |
1 files changed, 98 insertions, 36 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 06d09681e6f..ad4f2e404d6 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -288,13 +288,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 +306,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)); @@ -1832,7 +1853,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; @@ -2537,11 +2558,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; @@ -3061,15 +3090,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 @@ -3841,9 +3861,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. */ @@ -4762,7 +4781,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); @@ -5084,16 +5103,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 +5147,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 +5186,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 +5251,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 +5330,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); @@ -8170,22 +8234,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); } |