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);
field, because other parts of the compiler know that such
expressions are always non-NULL. */
if (!virtual_access && integer_zerop (offset))
- return build_nop (build_pointer_type (target_type), expr);
+ {
+ tree class_type;
+ /* TARGET_TYPE has been extracted from BINFO, and, is
+ therefore always cv-unqualified. Extract the
+ cv-qualifiers from EXPR so that the expression returned
+ matches the input. */
+ class_type = TREE_TYPE (TREE_TYPE (expr));
+ target_type
+ = cp_build_qualified_type (target_type,
+ cp_type_quals (class_type));
+ return build_nop (build_pointer_type (target_type), expr);
+ }
null_test = error_mark_node;
}
v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
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);
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;
/* Transform `(a, b).x' into `(*(a, &b)).x', `(a ? b : c).x'
into `(*(a ? &b : &c)).x', and so on. A COND_EXPR is only
- an lvalue in the frontend; only _DECLs and _REFs are lvalues
- in the backend. */
+ an lvalue in the front end; only _DECLs and _REFs are lvalues
+ in the back end. */
temp = unary_complex_lvalue (ADDR_EXPR, expr);
if (temp)
expr = build_indirect_ref (temp, NULL);
tree pointer_type;
pointer_type = build_pointer_type (expr_type);
+
+ /* 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 = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
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;
TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype);
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype);
+ TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (basetype);
}
}
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);
}
if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t))
}
/* Make BINFO's vtable have N entries, including RTTI entries,
- vbase and vcall offsets, etc. Set its type and call the backend
+ vbase and vcall offsets, etc. Set its type and call the back end
to lay it out. */
static void
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. */
fixed_offset, virtual_offset);
}
else
- gcc_assert (!DECL_THUNK_P (fn));
+ gcc_assert (DECL_INVALID_OVERRIDER_P (overrider_target) ||
+ !DECL_THUNK_P (fn));
/* Assume that we will produce a thunk that convert all the way to
the final overrider, and not to an intermediate virtual base. */
if (!DECL_VINDEX (decl))
DECL_VINDEX (decl) = error_mark_node;
IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
- if (DECL_DLLIMPORT_P (decl))
- {
- /* When we handled the dllimport attribute we may not have known
- that this function is virtual We can't use dllimport
- semantics for a virtual method because we need to initialize
- the vtable entry with a constant address. */
- DECL_DLLIMPORT_P (decl) = 0;
- DECL_ATTRIBUTES (decl)
- = remove_attribute ("dllimport", DECL_ATTRIBUTES (decl));
- }
}
}
while (base_fndecls)
{
/* Here we know it is a hider, and no overrider exists. */
- warning (0, "%q+D was hidden", TREE_VALUE (base_fndecls));
- warning (0, " by %q+D", fns);
+ warning (OPT_Woverloaded_virtual, "%q+D was hidden", TREE_VALUE (base_fndecls));
+ warning (OPT_Woverloaded_virtual, " by %q+D", fns);
base_fndecls = TREE_CHAIN (base_fndecls);
}
}
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)
+ pedwarn ("%q+#D invalid; an anonymous union can "
+ "only have non-static data members", elt);
+ else
+ pedwarn ("%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)
+ pedwarn ("private member %q+#D in anonymous union", elt);
+ else
+ pedwarn ("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)
+ pedwarn ("protected member %q+#D in anonymous union", elt);
+ else
+ pedwarn ("protected member %q+#D in anonymous struct", elt);
+ }
TREE_PRIVATE (elt) = TREE_PRIVATE (field);
TREE_PROTECTED (elt) = TREE_PROTECTED (field);
/* 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);
if (!INTEGRAL_TYPE_P (type))
{
error ("bit-field %q+#D with non-integral type", field);
- TREE_TYPE (field) = error_mark_node;
w = error_mark_node;
}
else
{
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;
}
}
|= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
+ TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (type);
}
if (!TYPE_HAS_CONST_INIT_REF (type))
/* 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,
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;
}
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))
|| 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));
/* Synthesize any needed methods. */
add_implicitly_declared_members (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. */
tree padding;
/* We still pass things that aren't non-static data members to
- the back-end, in case it wants to do something with them. */
+ the back end, in case it wants to do something with them. */
if (TREE_CODE (field) != FIELD_DECL)
{
place_field (rli, field);
place_field (rli,
build_decl (FIELD_DECL, NULL_TREE, char_type_node));
- /* Let the back-end lay out the type. */
+ /* Let the back end lay out the type. */
finish_record_layout (rli, /*free_p=*/true);
/* Warn about bases that can't be talked about due to ambiguity. */
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);
+ 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:
}
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;
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);
}
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. */
- error ("declaration of %q#D", decl);
- error ("changes meaning of %qD from %q+#D",
- DECL_NAME (OVL_CURRENT (decl)), (tree) n->value);
+ pedwarn ("declaration of %q#D", decl);
+ pedwarn ("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)