diff options
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r-- | gcc/cp/class.c | 309 |
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); } |