/* Functions related to building classes and their related objects.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* High-level class interface. */
static tree build_vtbl_initializer (tree, tree, tree, tree, int *);
static int count_fields (tree);
static int add_fields_to_record_type (tree, struct sorted_fields_type*, int);
-static void check_bitfield_decl (tree);
+static bool check_bitfield_decl (tree);
static void check_field_decl (tree, tree, int *, int *, int *);
static void check_field_decls (tree, tree *, int *, int *);
static tree *build_base_field (record_layout_info, tree, splay_tree, tree *);
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 (tree, tree, splay_tree);
+static bool layout_empty_base (record_layout_info, tree, tree, splay_tree);
static void accumulate_vtbl_inits (tree, tree, tree, tree, tree);
static tree dfs_accumulate_vtbl_inits (tree, tree, tree, tree,
tree);
if (!want_pointer)
/* This must happen before the call to save_expr. */
- expr = build_unary_op (ADDR_EXPR, expr, 0);
+ expr = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error);
offset = BINFO_OFFSET (binfo);
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
/* Do we need to look in the vtable for the real offset? */
virtual_access = (v_binfo && fixed_type_p <= 0);
+ /* Don't bother with the calculations inside sizeof; they'll ICE if the
+ source type is incomplete and the pointer value doesn't matter. */
+ if (cp_unevaluated_operand != 0)
+ {
+ expr = build_nop (build_pointer_type (target_type), expr);
+ if (!want_pointer)
+ expr = build_indirect_ref (EXPR_LOCATION (expr), expr, NULL);
+ return expr;
+ }
+
/* Do we need to check for a null pointer? */
if (want_pointer && !nonnull)
{
interesting to the optimizers anyway. */
&& !has_empty)
{
- expr = build_indirect_ref (expr, NULL);
+ expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
expr = build_simple_base_path (expr, binfo);
if (want_pointer)
expr = build_address (expr);
t = TREE_TYPE (TYPE_VFIELD (current_class_type));
t = build_pointer_type (t);
v_offset = convert (t, current_vtt_parm);
- v_offset = build_indirect_ref (v_offset, NULL);
+ v_offset = cp_build_indirect_ref (v_offset, NULL,
+ tf_warning_or_error);
}
else
- v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
+ v_offset = build_vfield_ref (cp_build_indirect_ref (expr, NULL,
+ tf_warning_or_error),
TREE_TYPE (TREE_TYPE (expr)));
- v_offset = build2 (PLUS_EXPR, TREE_TYPE (v_offset),
- v_offset, BINFO_VPTR_FIELD (v_binfo));
+ v_offset = build2 (POINTER_PLUS_EXPR, TREE_TYPE (v_offset),
+ v_offset, fold_convert (sizetype, BINFO_VPTR_FIELD (v_binfo)));
v_offset = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
v_offset);
- v_offset = build_indirect_ref (v_offset, NULL);
+ v_offset = cp_build_indirect_ref (v_offset, NULL, tf_warning_or_error);
TREE_CONSTANT (v_offset) = 1;
- TREE_INVARIANT (v_offset) = 1;
offset = convert_to_integer (ptrdiff_type_node,
size_diffop (offset,
expr = build1 (NOP_EXPR, ptr_target_type, expr);
if (!integer_zerop (offset))
- expr = build2 (code, ptr_target_type, expr, offset);
+ {
+ offset = fold_convert (sizetype, offset);
+ if (code == MINUS_EXPR)
+ offset = fold_build1 (NEGATE_EXPR, sizetype, offset);
+ expr = build2 (POINTER_PLUS_EXPR, ptr_target_type, expr, offset);
+ }
else
null_test = NULL;
if (!want_pointer)
- expr = build_indirect_ref (expr, NULL);
+ expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
out:
if (null_test)
in the back end. */
temp = unary_complex_lvalue (ADDR_EXPR, expr);
if (temp)
- expr = build_indirect_ref (temp, NULL);
+ expr = cp_build_indirect_ref (temp, NULL, tf_warning_or_error);
return expr;
}
tree pointer_type;
pointer_type = build_pointer_type (expr_type);
- expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
+
+ /* We use fold_build2 and fold_convert below to simplify the trees
+ provided to the optimizers. It is not safe to call these functions
+ when processing a template because they do not handle C++-specific
+ trees. */
+ gcc_assert (!processing_template_decl);
+ expr = cp_build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1,
+ tf_warning_or_error);
if (!integer_zerop (BINFO_OFFSET (base)))
- expr = build2 (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);
+ expr = fold_build2 (POINTER_PLUS_EXPR, pointer_type, expr,
+ fold_convert (sizetype, BINFO_OFFSET (base)));
+ expr = fold_convert (build_pointer_type (BINFO_TYPE (base)), expr);
+ expr = build_fold_indirect_ref (expr);
}
return expr;
if (!vtbl)
vtbl = build_vfield_ref (instance, basetype);
- assemble_external (vtbl);
- aref = build_array_ref (vtbl, idx);
+ aref = build_array_ref (input_location, vtbl, idx);
TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx);
- TREE_INVARIANT (aref) = TREE_CONSTANT (aref);
return aref;
}
{
tree aref;
- aref = build_vtbl_ref_1 (build_indirect_ref (instance_ptr, 0), idx);
+ aref = build_vtbl_ref_1 (cp_build_indirect_ref (instance_ptr, 0,
+ tf_warning_or_error),
+ idx);
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
if (TARGET_VTABLE_USES_DESCRIPTORS)
aref = build1 (NOP_EXPR, TREE_TYPE (aref),
- build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
+ cp_build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1,
+ tf_warning_or_error));
/* Remember this as a method reference, for later devirtualization. */
aref = build3 (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
if (complete)
{
DECL_EXTERNAL (decl) = 1;
- finish_decl (decl, NULL_TREE, NULL_TREE);
+ cp_finish_decl (decl, NULL_TREE, false, NULL_TREE, 0);
}
return decl;
CLASSTYPE_METHOD_VEC (type) = method_vec;
}
- /* Maintain TYPE_HAS_CONSTRUCTOR, etc. */
+ /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */
grok_special_member_properties (method);
/* Constructors and destructors go in special slots. */
coming from the using class in overload resolution. */
if (! DECL_STATIC_FUNCTION_P (fn)
&& ! DECL_STATIC_FUNCTION_P (method)
+ && TREE_TYPE (TREE_VALUE (parms1)) != error_mark_node
+ && TREE_TYPE (TREE_VALUE (parms2)) != error_mark_node
&& (TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms1)))
!= TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms2)))))
continue;
BINFO_VIRTUALS (type_binfo) = BINFO_VIRTUALS (primary);
}
}
-\f
-/* Set memoizing fields and bits of T (and its variants) for later
- use. */
-static void
-finish_struct_bits (tree t)
+/* Update the variant types of T. */
+
+void
+fixup_type_variants (tree t)
{
tree variants;
- /* Fix up variants (if any). */
+ if (!t)
+ return;
+
for (variants = TYPE_NEXT_VARIANT (t);
variants;
variants = TYPE_NEXT_VARIANT (variants))
{
/* These fields are in the _TYPE part of the node, not in
the TYPE_LANG_SPECIFIC component, so they are not shared. */
- TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
+ TYPE_HAS_USER_CONSTRUCTOR (variants) = TYPE_HAS_USER_CONSTRUCTOR (t);
TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
TYPE_VFIELD (variants) = TYPE_VFIELD (t);
TYPE_METHODS (variants) = TYPE_METHODS (t);
TYPE_FIELDS (variants) = TYPE_FIELDS (t);
+
+ /* All variants of a class have the same attributes. */
+ TYPE_ATTRIBUTES (variants) = TYPE_ATTRIBUTES (t);
}
+}
+
+\f
+/* Set memoizing fields and bits of T (and its variants) for later
+ use. */
+
+static void
+finish_struct_bits (tree t)
+{
+ /* Fix up variants (if any). */
+ fixup_type_variants (t);
if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t))
/* For a class w/o baseclasses, 'finish_struct' has set
DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode;
for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants))
{
- TYPE_MODE (variants) = BLKmode;
+ SET_TYPE_MODE (variants, BLKmode);
TREE_ADDRESSABLE (variants) = 1;
}
}
return;
}
- if (TYPE_HAS_CONSTRUCTOR (t)
+ /* Warn about classes that have private constructors and no friends. */
+ if (TYPE_HAS_USER_CONSTRUCTOR (t)
/* Implicitly generated constructors are always public. */
&& (!CLASSTYPE_LAZY_DEFAULT_CTOR (t)
|| !CLASSTYPE_LAZY_COPY_CTOR (t)))
have the same signature. */
int
-same_signature_p (tree fndecl, tree base_fndecl)
+same_signature_p (const_tree fndecl, const_tree base_fndecl)
{
/* One destructor overrides another if they are the same kind of
destructor. */
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
+ bool is_union = TREE_CODE (TREE_TYPE (field)) == UNION_TYPE;
tree elt = TYPE_FIELDS (TREE_TYPE (field));
for (; elt; elt = TREE_CHAIN (elt))
{
if (TREE_CODE (elt) != FIELD_DECL)
{
- pedwarn ("%q+#D invalid; an anonymous union can "
- "only have non-static data members", elt);
+ if (is_union)
+ permerror (input_location, "%q+#D invalid; an anonymous union can "
+ "only have non-static data members", elt);
+ else
+ permerror (input_location, "%q+#D invalid; an anonymous struct can "
+ "only have non-static data members", elt);
continue;
}
if (TREE_PRIVATE (elt))
- pedwarn ("private member %q+#D in anonymous union", elt);
+ {
+ if (is_union)
+ permerror (input_location, "private member %q+#D in anonymous union", elt);
+ else
+ permerror (input_location, "private member %q+#D in anonymous struct", elt);
+ }
else if (TREE_PROTECTED (elt))
- pedwarn ("protected member %q+#D in anonymous union", elt);
+ {
+ if (is_union)
+ permerror (input_location, "protected member %q+#D in anonymous union", elt);
+ else
+ permerror (input_location, "protected member %q+#D in anonymous struct", elt);
+ }
TREE_PRIVATE (elt) = TREE_PRIVATE (field);
TREE_PROTECTED (elt) = TREE_PROTECTED (field);
}
}
- /* Default constructor. */
- if (! TYPE_HAS_CONSTRUCTOR (t))
+ /* [class.ctor]
+
+ If there is no user-declared constructor for a class, a default
+ constructor is implicitly declared. */
+ if (! TYPE_HAS_USER_CONSTRUCTOR (t))
{
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
}
- /* Copy constructor. */
+ /* [class.ctor]
+
+ If a class definition does not explicitly declare a copy
+ constructor, one is declared implicitly. */
if (! TYPE_HAS_INIT_REF (t) && ! TYPE_FOR_JAVA (t))
{
TYPE_HAS_INIT_REF (t) = 1;
TYPE_HAS_CONST_INIT_REF (t) = !cant_have_const_cctor;
CLASSTYPE_LAZY_COPY_CTOR (t) = 1;
- TYPE_HAS_CONSTRUCTOR (t) = 1;
}
/* If there is no assignment operator, one will be created if and
/* FIELD is a bit-field. We are finishing the processing for its
enclosing type. Issue any appropriate messages and set appropriate
- flags. */
+ flags. Returns false if an error has been diagnosed. */
-static void
+static bool
check_bitfield_decl (tree field)
{
tree type = TREE_TYPE (field);
DECL_INITIAL (field) = NULL_TREE;
/* Detect invalid bit-field type. */
- if (!INTEGRAL_TYPE_P (type))
+ if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
error ("bit-field %q+#D with non-integral type", field);
- TREE_TYPE (field) = error_mark_node;
w = error_mark_node;
}
else
warning (0, "width of %q+D exceeds its type", field);
else if (TREE_CODE (type) == ENUMERAL_TYPE
&& (0 > compare_tree_int (w,
- min_precision (TYPE_MIN_VALUE (type),
- TYPE_UNSIGNED (type)))
+ tree_int_cst_min_precision
+ (TYPE_MIN_VALUE (type),
+ TYPE_UNSIGNED (type)))
|| 0 > compare_tree_int (w,
- min_precision
+ tree_int_cst_min_precision
(TYPE_MAX_VALUE (type),
TYPE_UNSIGNED (type)))))
warning (0, "%q+D is too small to hold all values of %q#T", field, type);
{
DECL_SIZE (field) = convert (bitsizetype, w);
DECL_BIT_FIELD (field) = 1;
+ return true;
}
else
{
/* Non-bit-fields are aligned for their type. */
DECL_BIT_FIELD (field) = 0;
CLEAR_DECL_C_BIT_FIELD (field);
+ return false;
}
}
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
CLASSTYPE_NON_AGGREGATE (t) = 1;
- /* If this is of reference type, check if it needs an init.
- Also do a little ANSI jig if necessary. */
+ /* If this is of reference type, check if it needs an init. */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
CLASSTYPE_NON_POD_P (t) = 1;
only way to initialize nonstatic const and reference
members. */
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
-
- if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
- && extra_warnings)
- warning (OPT_Wextra, "non-static reference %q+#D in class without a constructor", x);
}
type = strip_array_types (type);
x);
cant_pack = 1;
}
- else if (TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
+ else if (DECL_C_BIT_FIELD (x)
+ || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
DECL_PACKED (x) = 1;
}
only way to initialize nonstatic const and reference
members. */
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
-
- if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
- && extra_warnings)
- warning (OPT_Wextra, "non-static const member %q+#D in class without a constructor", x);
}
/* A field that is pseudo-const makes the structure likewise. */
else if (CLASS_TYPE_P (type))
/* Core issue 80: A nonstatic data member is required to have a
different name from the class iff the class has a
- user-defined constructor. */
- if (constructor_name_p (DECL_NAME (x), t) && TYPE_HAS_CONSTRUCTOR (t))
- pedwarn ("field %q+#D with same name as class", x);
+ user-declared constructor. */
+ if (constructor_name_p (DECL_NAME (x), t)
+ && TYPE_HAS_USER_CONSTRUCTOR (t))
+ permerror (input_location, "field %q+#D with same name as class", x);
/* We set DECL_C_BIT_FIELD in grokbitfield.
If the type and width are valid, we'll also set DECL_BIT_FIELD. */
- if (DECL_C_BIT_FIELD (x))
- check_bitfield_decl (x);
- else
+ if (! DECL_C_BIT_FIELD (x) || ! check_bitfield_decl (x))
check_field_decl (x, t,
cant_have_const_ctor_p,
no_const_asn_ref_p,
This seems enough for practical purposes. */
if (warn_ecpp
&& has_pointers
- && TYPE_HAS_CONSTRUCTOR (t)
+ && TYPE_HAS_USER_CONSTRUCTOR (t)
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
&& !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
{
type. Return nonzero iff we added it at the end. */
static bool
-layout_empty_base (tree binfo, tree eoc, splay_tree offsets)
+layout_empty_base (record_layout_info rli, tree binfo,
+ tree eoc, splay_tree offsets)
{
tree alignment;
tree basetype = BINFO_TYPE (binfo);
propagate_binfo_offsets (binfo, alignment);
}
}
+
+ if (CLASSTYPE_USER_ALIGN (basetype))
+ {
+ rli->record_align = MAX (rli->record_align, CLASSTYPE_ALIGN (basetype));
+ if (warn_packed)
+ rli->unpacked_align = MAX (rli->unpacked_align, CLASSTYPE_ALIGN (basetype));
+ TYPE_USER_ALIGN (rli->t) = 1;
+ }
+
return atend;
}
CLASSTYPE_EMPTY_P (t) = 0;
/* Create the FIELD_DECL. */
- decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype));
+ decl = build_decl (input_location,
+ FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype));
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);
- DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
- DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
- DECL_MODE (decl) = TYPE_MODE (basetype);
- DECL_FIELD_IS_BASE (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. */
- layout_nonempty_base_or_field (rli, decl, binfo, offsets);
- /* Add the new FIELD_DECL to the list of fields for T. */
- TREE_CHAIN (decl) = *next_field;
- *next_field = decl;
- next_field = &TREE_CHAIN (decl);
+ if (CLASSTYPE_AS_BASE (basetype))
+ {
+ DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
+ DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
+ DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
+ DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
+ DECL_MODE (decl) = TYPE_MODE (basetype);
+ DECL_FIELD_IS_BASE (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. */
+ layout_nonempty_base_or_field (rli, decl, binfo, offsets);
+ /* Add the new FIELD_DECL to the list of fields for T. */
+ TREE_CHAIN (decl) = *next_field;
+ *next_field = decl;
+ next_field = &TREE_CHAIN (decl);
+ }
}
else
{
byte-aligned. */
eoc = round_up (rli_size_unit_so_far (rli),
CLASSTYPE_ALIGN_UNIT (basetype));
- atend = layout_empty_base (binfo, eoc, offsets);
+ atend = layout_empty_base (rli, binfo, eoc, 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))
if (DECL_PURE_VIRTUAL_P (x))
VEC_safe_push (tree, gc, CLASSTYPE_PURE_VIRTUALS (t), x);
}
- /* All user-declared destructors are non-trivial. */
- if (DECL_DESTRUCTOR_P (x))
+ /* All user-provided destructors are non-trivial. */
+ if (DECL_DESTRUCTOR_P (x) && !DECL_DEFAULTED_FN (x))
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1;
}
}
clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
}
+/* Returns true iff class T has a user-defined constructor other than
+ the default constructor. */
+
+bool
+type_has_user_nondefault_constructor (tree t)
+{
+ tree fns;
+
+ if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ return false;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (!DECL_ARTIFICIAL (fn)
+ && (TREE_CODE (fn) == TEMPLATE_DECL
+ || (skip_artificial_parms_for (fn, DECL_ARGUMENTS (fn))
+ != NULL_TREE)))
+ return true;
+ }
+
+ return false;
+}
+
+/* Returns true iff FN is a user-provided function, i.e. user-declared
+ and not defaulted at its first declaration. */
+
+static bool
+user_provided_p (tree fn)
+{
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ return true;
+ else
+ return (!DECL_ARTIFICIAL (fn)
+ && !(DECL_DEFAULTED_FN (fn)
+ && DECL_INITIALIZED_IN_CLASS_P (fn)));
+}
+
+/* Returns true iff class T has a user-provided constructor. */
+
+bool
+type_has_user_provided_constructor (tree t)
+{
+ tree fns;
+
+ if (!CLASS_TYPE_P (t))
+ return false;
+
+ if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ return false;
+
+ /* This can happen in error cases; avoid crashing. */
+ if (!CLASSTYPE_METHOD_VEC (t))
+ return false;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ if (user_provided_p (OVL_CURRENT (fns)))
+ return true;
+
+ return false;
+}
+
+/* Returns true iff class T has a user-provided default constructor. */
+
+bool
+type_has_user_provided_default_constructor (tree t)
+{
+ tree fns, args;
+
+ if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ return false;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (TREE_CODE (fn) == FUNCTION_DECL
+ && user_provided_p (fn))
+ {
+ args = FUNCTION_FIRST_USER_PARMTYPE (fn);
+ while (args && TREE_PURPOSE (args))
+ args = TREE_CHAIN (args);
+ if (!args || args == void_list_node)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Returns true if FN can be explicitly defaulted. */
+
+bool
+defaultable_fn_p (tree fn)
+{
+ if (DECL_CONSTRUCTOR_P (fn))
+ {
+ if (FUNCTION_FIRST_USER_PARMTYPE (fn) == void_list_node)
+ return true;
+ else if (copy_fn_p (fn) > 0
+ && (TREE_CHAIN (FUNCTION_FIRST_USER_PARMTYPE (fn))
+ == void_list_node))
+ return true;
+ else
+ return false;
+ }
+ else if (DECL_DESTRUCTOR_P (fn))
+ return true;
+ else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
+ && DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR)
+ return copy_fn_p (fn);
+ else
+ return false;
+}
+
/* Remove all zero-width bit-fields from T. */
static void
second_parm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
if (second_parm == void_list_node)
return false;
+ /* Do not consider this function if its second argument is an
+ ellipsis. */
+ if (!second_parm)
+ continue;
/* Otherwise, if we have a two-argument function and the second
argument is `size_t', it will be the usual deallocation
function -- unless there is one-argument function, too. */
should take a non-const reference argument. */
int no_const_asn_ref;
tree access_decls;
+ bool saved_complex_asn_ref;
+ bool saved_nontrivial_dtor;
/* By default, we use const reference arguments and generate default
constructors. */
/* Check all the method declarations. */
check_methods (t);
+ /* Save the initial values of these flags which only indicate whether
+ or not the class has user-provided functions. As we analyze the
+ bases and members we can set these flags for other reasons. */
+ saved_complex_asn_ref = TYPE_HAS_COMPLEX_ASSIGN_REF (t);
+ saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
+
/* Check all the data member declarations. We cannot call
check_field_decls until we have called check_bases check_methods,
as check_field_decls depends on TYPE_HAS_NONTRIVIAL_DESTRUCTOR
/* Do some bookkeeping that will guide the generation of implicitly
declared member functions. */
- TYPE_HAS_COMPLEX_INIT_REF (t)
- |= (TYPE_HAS_INIT_REF (t) || TYPE_CONTAINS_VPTR_P (t));
+ TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_CONTAINS_VPTR_P (t);
+ /* We need to call a constructor for this class if it has a
+ user-provided constructor, or if the default constructor is going
+ to initialize the vptr. (This is not an if-and-only-if;
+ TYPE_NEEDS_CONSTRUCTING is set elsewhere if bases or members
+ themselves need constructing.) */
TYPE_NEEDS_CONSTRUCTING (t)
- |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_CONTAINS_VPTR_P (t));
+ |= (type_has_user_provided_constructor (t) || TYPE_CONTAINS_VPTR_P (t));
+ /* [dcl.init.aggr]
+
+ An aggregate is an array or a class with no user-provided
+ constructors ... and no virtual functions.
+
+ Again, other conditions for being an aggregate are checked
+ elsewhere. */
CLASSTYPE_NON_AGGREGATE (t)
- |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_POLYMORPHIC_P (t));
+ |= (type_has_user_provided_constructor (t) || TYPE_POLYMORPHIC_P (t));
CLASSTYPE_NON_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t)
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
- || TYPE_HAS_ASSIGN_REF (t));
- TYPE_HAS_COMPLEX_ASSIGN_REF (t)
- |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
- TYPE_HAS_COMPLEX_DFLT (t)
- |= (TYPE_HAS_DEFAULT_CONSTRUCTOR (t) || TYPE_CONTAINS_VPTR_P (t));
+ || saved_nontrivial_dtor || saved_complex_asn_ref);
+ TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_CONTAINS_VPTR_P (t);
+ TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t);
+
+ /* If the class has no user-declared constructor, but does have
+ non-static const or reference data members that can never be
+ initialized, issue a warning. */
+ if (warn_uninitialized
+ /* Classes with user-declared constructors are presumed to
+ initialize these members. */
+ && !TYPE_HAS_USER_CONSTRUCTOR (t)
+ /* Aggregates can be initialized with brace-enclosed
+ initializers. */
+ && CLASSTYPE_NON_AGGREGATE (t))
+ {
+ tree field;
+
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ {
+ tree type;
+
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ type = TREE_TYPE (field);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ warning (OPT_Wuninitialized, "non-static reference %q+#D "
+ "in class without a constructor", field);
+ else if (CP_TYPE_CONST_P (type)
+ && (!CLASS_TYPE_P (type)
+ || !TYPE_HAS_DEFAULT_CONSTRUCTOR (type)))
+ warning (OPT_Wuninitialized, "non-static const member %q+#D "
+ "in class without a constructor", field);
+ }
+ }
/* Synthesize any needed methods. */
add_implicitly_declared_members (t,
stores cannot alias stores to void*! */
tree field;
- field = build_decl (FIELD_DECL, get_vfield_name (t), vtbl_ptr_type_node);
+ field = build_decl (input_location,
+ FIELD_DECL, get_vfield_name (t), vtbl_ptr_type_node);
DECL_VIRTUAL_P (field) = 1;
DECL_ARTIFICIAL (field) = 1;
DECL_FIELD_CONTEXT (field) = t;
{
tree size;
- if (is_empty_class (BINFO_TYPE (binfo)))
+ if (!CLASSTYPE_AS_BASE (BINFO_TYPE (binfo)))
+ size = TYPE_SIZE_UNIT (char_type_node);
+ else if (is_empty_class (BINFO_TYPE (binfo)))
/* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
allocate some space for it. It cannot have virtual bases, so
TYPE_SIZE_UNIT is fine. */
if (DECL_C_BIT_FIELD (field)
&& INT_CST_LT (TYPE_SIZE (type), DECL_SIZE (field)))
{
- integer_type_kind itk;
+ unsigned int itk;
tree integer_type;
bool was_unnamed_p = false;
/* We must allocate the bits as if suitably aligned for the
must be converted to the type given the bitfield here. */
if (DECL_C_BIT_FIELD (field))
{
- tree ftype;
unsigned HOST_WIDE_INT width;
- ftype = TREE_TYPE (field);
+ tree ftype = TREE_TYPE (field);
width = tree_low_cst (DECL_SIZE (field), /*unsignedp=*/1);
if (width != TYPE_PRECISION (ftype))
- TREE_TYPE (field)
- = c_build_bitfield_integer_type (width,
- TYPE_UNSIGNED (ftype));
+ {
+ TREE_TYPE (field)
+ = c_build_bitfield_integer_type (width,
+ TYPE_UNSIGNED (ftype));
+ TREE_TYPE (field)
+ = cp_build_qualified_type (TREE_TYPE (field),
+ TYPE_QUALS (ftype));
+ }
}
/* If we needed additional padding after this field, add it
{
tree padding_field;
- padding_field = build_decl (FIELD_DECL,
+ padding_field = build_decl (input_location,
+ FIELD_DECL,
NULL_TREE,
char_type_node);
DECL_BIT_FIELD (padding_field) = 1;
remove_zero_width_bit_fields (t);
/* Create the version of T used for virtual bases. We do not use
- make_aggr_type for this version; this is an artificial type. For
+ make_class_type for this version; this is an artificial type. For
a POD type, we just reuse T. */
if (CLASSTYPE_NON_POD_P (t) || CLASSTYPE_EMPTY_P (t))
{
for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
- *next_field = build_decl (FIELD_DECL,
+ *next_field = build_decl (input_location,
+ FIELD_DECL,
DECL_NAME (field),
TREE_TYPE (field));
DECL_CONTEXT (*next_field) = base_t;
/* Make sure not to create any structures with zero size. */
if (integer_zerop (rli_size_unit_so_far (rli)) && CLASSTYPE_EMPTY_P (t))
place_field (rli,
- build_decl (FIELD_DECL, NULL_TREE, char_type_node));
+ build_decl (input_location,
+ FIELD_DECL, NULL_TREE, char_type_node));
/* Let the back end lay out the type. */
finish_record_layout (rli, /*free_p=*/true);
if (COMPLETE_TYPE_P (t))
{
- gcc_assert (IS_AGGR_TYPE (t));
+ gcc_assert (MAYBE_CLASS_TYPE_P (t));
error ("redefinition of %q#T", t);
popclass ();
return;
tree dtor;
dtor = CLASSTYPE_DESTRUCTORS (t);
- /* Warn only if the dtor is non-private or the class has
- friends. */
if (/* An implicitly declared destructor is always public. And,
if it were virtual, we would have created it by now. */
!dtor
|| (!DECL_VINDEX (dtor)
- && (!TREE_PRIVATE (dtor)
- || CLASSTYPE_FRIEND_CLASSES (t)
- || DECL_FRIENDLIST (TYPE_MAIN_DECL (t)))))
- warning (0, "%q#T has virtual functions but non-virtual destructor",
- t);
+ && (/* public non-virtual */
+ (!TREE_PRIVATE (dtor) && !TREE_PROTECTED (dtor))
+ || (/* non-public non-virtual with friends */
+ (TREE_PRIVATE (dtor) || TREE_PROTECTED (dtor))
+ && (CLASSTYPE_FRIEND_CLASSES (t)
+ || DECL_FRIENDLIST (TYPE_MAIN_DECL (t)))))))
+ warning (OPT_Wnon_virtual_dtor,
+ "%q#T has virtual functions and accessible"
+ " non-virtual destructor", t);
}
complete_vars (t);
before this function is called. */
static tree
-fixed_type_or_null (tree instance, int* nonnull, int* cdtorp)
+fixed_type_or_null (tree instance, int *nonnull, int *cdtorp)
{
+#define RECUR(T) fixed_type_or_null((T), nonnull, cdtorp)
+
switch (TREE_CODE (instance))
{
case INDIRECT_REF:
if (POINTER_TYPE_P (TREE_TYPE (instance)))
return NULL_TREE;
else
- return fixed_type_or_null (TREE_OPERAND (instance, 0),
- nonnull, cdtorp);
+ return RECUR (TREE_OPERAND (instance, 0));
case CALL_EXPR:
/* This is a call to a constructor, hence it's never zero. */
*nonnull = 1;
return TREE_TYPE (instance);
}
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
+ return RECUR (TREE_OPERAND (instance, 0));
+ case POINTER_PLUS_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
+ return RECUR (TREE_OPERAND (instance, 0));
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
+ return RECUR (TREE_OPERAND (instance, 0));
+
return NULL_TREE;
- case NOP_EXPR:
- case CONVERT_EXPR:
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
+ CASE_CONVERT:
+ return RECUR (TREE_OPERAND (instance, 0));
case ADDR_EXPR:
instance = TREE_OPERAND (instance, 0);
if (t && DECL_P (t))
*nonnull = 1;
}
- return fixed_type_or_null (instance, nonnull, cdtorp);
+ return RECUR (instance);
case COMPONENT_REF:
/* If this component is really a base class reference, then the field
itself isn't definitive. */
if (DECL_FIELD_IS_BASE (TREE_OPERAND (instance, 1)))
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
- return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull, cdtorp);
+ return RECUR (TREE_OPERAND (instance, 0));
+ return RECUR (TREE_OPERAND (instance, 1));
case VAR_DECL:
case FIELD_DECL:
if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE
- && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (instance))))
+ && MAYBE_CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (instance))))
{
if (nonnull)
*nonnull = 1;
case TARGET_EXPR:
case PARM_DECL:
case RESULT_DECL:
- if (IS_AGGR_TYPE (TREE_TYPE (instance)))
+ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (instance)))
{
if (nonnull)
*nonnull = 1;
}
else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
{
+ /* We only need one hash table because it is always left empty. */
+ static htab_t ht;
+ if (!ht)
+ ht = htab_create (37,
+ htab_hash_pointer,
+ htab_eq_pointer,
+ /*htab_del=*/NULL);
+
/* Reference variables should be references to objects. */
if (nonnull)
*nonnull = 1;
- /* DECL_VAR_MARKED_P is used to prevent recursion; a
+ /* Enter the INSTANCE in a table 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))
+ && !htab_find (ht, 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;
+ void **slot;
+
+ slot = htab_find_slot (ht, instance, INSERT);
+ *slot = instance;
+ type = RECUR (DECL_INITIAL (instance));
+ htab_remove_elt (ht, instance);
+
return type;
}
}
default:
return NULL_TREE;
}
+#undef RECUR
}
/* Return nonzero if the dynamic type of INSTANCE is known, and
{
tree t = TREE_TYPE (instance);
int cdtorp = 0;
-
tree fixed = fixed_type_or_null (instance, nonnull, &cdtorp);
if (fixed == NULL_TREE)
return 0;
{
int i;
+ if (!CLASS_TYPE_P (t))
+ return false;
+
/* We start looking from 1 because entry 0 is from global scope,
and has no type. */
for (i = current_class_depth; i > 0; --i)
void
push_nested_class (tree type)
{
- tree context;
-
/* A namespace might be passed in error cases, like A::B:C. */
if (type == NULL_TREE
- || type == error_mark_node
- || TREE_CODE (type) == NAMESPACE_DECL
- || ! IS_AGGR_TYPE (type)
- || TREE_CODE (type) == TEMPLATE_TYPE_PARM
- || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ || !CLASS_TYPE_P (type))
return;
- context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
+ push_nested_class (DECL_CONTEXT (TYPE_MAIN_DECL (type)));
- if (context && CLASS_TYPE_P (context))
- push_nested_class (context);
pushclass (type);
}
control of FLAGS. Permit pointers to member function if FLAGS
permits. If TEMPLATE_ONLY, the name of the overloaded function was
a template-id, and EXPLICIT_TARGS are the explicitly provided
- template arguments. If OVERLOAD is for one or more member
- functions, then ACCESS_PATH is the base path used to reference
- those member functions. */
+ template arguments.
+
+ If OVERLOAD is for one or more member functions, then ACCESS_PATH
+ is the base path used to reference those member functions. If
+ TF_NO_ACCESS_CONTROL is not set in FLAGS, and the address is
+ resolved to a member function, access checks will be performed and
+ errors issued if appropriate. */
static tree
resolve_address_of_overloaded_function (tree target_type,
tree target_arg_types;
tree target_ret_type;
tree fns;
+ tree *args;
+ unsigned int nargs, ia;
+ tree arg;
if (is_ptrmem)
target_fn_type
if (TREE_CODE (target_fn_type) == METHOD_TYPE)
target_arg_types = TREE_CHAIN (target_arg_types);
+ nargs = list_length (target_arg_types);
+ args = XALLOCAVEC (tree, nargs);
+ for (arg = target_arg_types, ia = 0;
+ arg != NULL_TREE && arg != void_list_node;
+ arg = TREE_CHAIN (arg), ++ia)
+ args[ia] = TREE_VALUE (arg);
+ nargs = ia;
+
for (fns = overload; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
/* Try to do argument deduction. */
targs = make_tree_vec (DECL_NTPARMS (fn));
- if (fn_type_unification (fn, explicit_targs, targs,
- target_arg_types, target_ret_type,
- DEDUCE_EXACT, LOOKUP_NORMAL))
+ if (fn_type_unification (fn, explicit_targs, targs, args, nargs,
+ target_ret_type, DEDUCE_EXACT,
+ LOOKUP_NORMAL))
/* Argument deduction failed. */
continue;
if (flags & tf_error)
{
error ("no matches converting function %qD to type %q#T",
- DECL_NAME (OVL_FUNCTION (overload)),
+ DECL_NAME (OVL_CURRENT (overload)),
target_type);
/* print_candidates expects a chain with the functions in
}
else if (TREE_CHAIN (matches))
{
- /* There were too many matches. */
+ /* There were too many matches. First check if they're all
+ the same function. */
+ tree match;
- if (flags & tf_error)
+ fn = TREE_PURPOSE (matches);
+ for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN (match))
+ if (!decls_match (fn, TREE_PURPOSE (match)))
+ break;
+
+ if (match)
{
- tree match;
+ if (flags & tf_error)
+ {
+ error ("converting overloaded function %qD to type %q#T is ambiguous",
+ DECL_NAME (OVL_FUNCTION (overload)),
+ target_type);
- error ("converting overloaded function %qD to type %q#T is ambiguous",
- DECL_NAME (OVL_FUNCTION (overload)),
- target_type);
+ /* Since print_candidates expects the functions in the
+ TREE_VALUE slot, we flip them here. */
+ for (match = matches; match; match = TREE_CHAIN (match))
+ TREE_VALUE (match) = TREE_PURPOSE (match);
- /* Since print_candidates expects the functions in the
- TREE_VALUE slot, we flip them here. */
- for (match = matches; match; match = TREE_CHAIN (match))
- TREE_VALUE (match) = TREE_PURPOSE (match);
+ print_candidates (matches);
+ }
- print_candidates (matches);
+ return error_mark_node;
}
-
- return error_mark_node;
}
/* Good, exactly one match. Now, convert it to the correct type. */
if (!(flags & tf_error))
return error_mark_node;
- pedwarn ("assuming pointer to member %qD", fn);
+ permerror (input_location, "assuming pointer to member %qD", fn);
if (!explained)
{
- pedwarn ("(a pointer to member can only be formed with %<&%E%>)", fn);
+ inform (input_location, "(a pointer to member can only be formed with %<&%E%>)", fn);
explained = 1;
}
}
function will be marked as used at this point. */
if (!(flags & tf_conv))
{
+ /* Make =delete work with SFINAE. */
+ if (DECL_DELETED_FN (fn) && !(flags & tf_error))
+ return error_mark_node;
+
mark_used (fn);
- /* We could not check access when this expression was originally
- created since we did not know at that time to which function
- the expression referred. */
- if (DECL_FUNCTION_MEMBER_P (fn))
- {
- gcc_assert (access_path);
- perform_or_defer_access_check (access_path, fn, fn);
- }
+ }
+
+ /* We could not check access to member functions when this
+ expression was originally created since we did not know at that
+ time to which function the expression referred. */
+ if (!(flags & tf_no_access_control)
+ && DECL_FUNCTION_MEMBER_P (fn))
+ {
+ gcc_assert (access_path);
+ perform_or_defer_access_check (access_path, fn, fn);
}
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
- return build_unary_op (ADDR_EXPR, fn, 0);
+ return cp_build_unary_op (ADDR_EXPR, fn, 0, flags);
else
{
- /* The target must be a REFERENCE_TYPE. Above, build_unary_op
+ /* The target must be a REFERENCE_TYPE. Above, cp_build_unary_op
will mark the function as addressed, but here we must do it
explicitly. */
cxx_mark_addressable (fn);
dependent on overload resolution. */
gcc_assert (TREE_CODE (rhs) == ADDR_EXPR
|| TREE_CODE (rhs) == COMPONENT_REF
- || TREE_CODE (rhs) == COMPOUND_EXPR
- || really_overloaded_fn (rhs));
-
- /* We don't overwrite rhs if it is an overloaded function.
- Copying it would destroy the tree link. */
- if (TREE_CODE (rhs) != OVERLOAD)
- rhs = copy_node (rhs);
+ || really_overloaded_fn (rhs)
+ || (flag_ms_extensions && TREE_CODE (rhs) == FUNCTION_DECL));
/* This should really only be used when attempting to distinguish
what sort of a pointer to function we have. For now, any
/*explicit_targs=*/NULL_TREE,
access_path);
- case COMPOUND_EXPR:
- TREE_OPERAND (rhs, 0)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
- if (TREE_OPERAND (rhs, 0) == error_mark_node)
- return error_mark_node;
- TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
- if (TREE_OPERAND (rhs, 1) == error_mark_node)
- return error_mark_node;
-
- TREE_TYPE (rhs) = lhstype;
- return rhs;
-
case ADDR_EXPR:
{
if (PTRMEM_OK_P (rhs))
if (type == error_mark_node)
return 0;
- if (! IS_AGGR_TYPE (type))
+ if (! CLASS_TYPE_P (type))
return 0;
/* In G++ 3.2, whether or not a class was empty was determined by
return false;
}
+/* Returns true if TYPE contains no actual data, just various
+ possible combinations of empty classes. */
+
+bool
+is_really_empty_class (tree type)
+{
+ if (is_empty_class (type))
+ return true;
+ if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ tree binfo;
+ tree base_binfo;
+ int i;
+
+ for (binfo = TYPE_BINFO (type), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
+ if (!is_really_empty_class (BINFO_TYPE (base_binfo)))
+ return false;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && !DECL_ARTIFICIAL (field)
+ && !is_really_empty_class (TREE_TYPE (field)))
+ return false;
+ return true;
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ return is_really_empty_class (TREE_TYPE (type));
+ return false;
+}
+
/* Note that NAME was looked up while the current class was being
defined and that the result of that lookup was DECL. */
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. */
- pedwarn ("declaration of %q#D", decl);
- pedwarn ("changes meaning of %qD from %q+#D",
+ permerror (input_location, "declaration of %q#D", decl);
+ permerror (input_location, "changes meaning of %qD from %q+#D",
DECL_NAME (OVL_CURRENT (decl)), (tree) n->value);
}
}
tree decl;
decl = BINFO_VTABLE (binfo);
- if (decl && TREE_CODE (decl) == PLUS_EXPR)
+ if (decl && TREE_CODE (decl) == POINTER_PLUS_EXPR)
{
gcc_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR);
decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
/* Figure out the type of the construction vtable. */
type = build_index_type (size_int (list_length (inits) - 1));
type = build_cplus_array_type (vtable_entry_type, type);
+ layout_type (type);
TREE_TYPE (vtbl) = type;
+ DECL_SIZE (vtbl) = DECL_SIZE_UNIT (vtbl) = NULL_TREE;
+ layout_decl (vtbl, 0);
/* Initialize the construction vtable. */
CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
index = size_binop (MULT_EXPR,
TYPE_SIZE_UNIT (vtable_entry_type),
index);
- vtbl = build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
+ vtbl = build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
}
if (ctor_vtbl_p)
We first check this in update_vtable_entry_for_fn, so we handle
restored primary bases properly; we also need to do it here so we
- zero out unused slots in ctor vtables, rather than filling themff
+ zero out unused slots in ctor vtables, rather than filling them
with erroneous values (though harmless, apart from relocation
costs). */
for (b = binfo; ; b = get_primary_binfo (b))
TREE_OPERAND (init, 0),
build_int_cst (NULL_TREE, i));
TREE_CONSTANT (fdesc) = 1;
- TREE_INVARIANT (fdesc) = 1;
vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits);
}