/* 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 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+ Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* High-level class interface. */
#include "target.h"
#include "convert.h"
#include "cgraph.h"
+#include "tree-dump.h"
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
/* If were defining TYPE, the names used in this class. */
splay_tree names_used;
+
+ /* Nonzero if this class is no longer open, because of a call to
+ push_to_top_level. */
+ size_t hidden;
}* class_stack_node_t;
typedef struct vtbl_init_data_s
static int current_class_stack_size;
static class_stack_node_t current_class_stack;
+/* The size of the largest empty class seen in this translation unit. */
+static GTY (()) tree sizeof_biggest_empty_class;
+
/* An array of all local classes present in this translation unit, in
declaration order. */
VEC(tree,gc) *local_classes;
static int resort_method_name_cmp (const void *, const void *);
static void add_implicitly_declared_members (tree, int, int);
static tree fixed_type_or_null (tree, int *, int *);
-static tree resolve_address_of_overloaded_function (tree, tree, tsubst_flags_t,
- bool, tree);
static tree build_simple_base_path (tree expr, tree binfo);
static tree build_vtbl_ref_1 (tree, tree);
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 tree dfs_find_final_overrider_post (tree, void *);
static tree find_final_overrider (tree, tree, tree);
static int make_new_vtable (tree, tree);
+static tree get_primary_binfo (tree);
static int maybe_indent_hierarchy (FILE *, int, int);
static tree dump_class_hierarchy_r (FILE *, int, tree, tree, int);
static void dump_class_hierarchy (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);
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, 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);
tree
build_base_path (enum tree_code code,
- tree expr,
- tree binfo,
- int nonnull)
+ tree expr,
+ tree binfo,
+ int nonnull)
{
tree v_binfo = NULL_TREE;
tree d_binfo = NULL_TREE;
&& SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), probe))
|| (code == PLUS_EXPR
&& SAME_BINFO_TYPE_P (BINFO_TYPE (d_binfo), probe)));
-
+
if (binfo == d_binfo)
/* Nothing to do. */
return expr;
offset = BINFO_OFFSET (binfo);
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
+ target_type = code == PLUS_EXPR ? BINFO_TYPE (binfo) : BINFO_TYPE (d_binfo);
/* Do we need to look in the vtable for the real offset? */
virtual_access = (v_binfo && fixed_type_p <= 0);
/* Do we need to check for a null pointer? */
- if (want_pointer && !nonnull && (virtual_access || !integer_zerop (offset)))
- null_test = error_mark_node;
+ if (want_pointer && !nonnull)
+ {
+ /* If we know the conversion will not actually change the value
+ of EXPR, then we can avoid testing the expression for NULL.
+ We have to avoid generating a COMPONENT_REF for a base class
+ field, because other parts of the compiler know that such
+ expressions are always non-NULL. */
+ if (!virtual_access && integer_zerop (offset))
+ {
+ 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;
+ }
/* Protect against multiple evaluation if necessary. */
if (TREE_SIDE_EFFECTS (expr) && (null_test || virtual_access))
if (virtual_access)
{
/* 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. */
+ 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;
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 = BINFO_INHERITANCE_CHAIN (v_binfo);
+ /* In a base member initializer, we cannot rely on the
+ vtable being set up. We have to indirect via the
+ vtt_parm. */
tree t;
- t = TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived)));
+ t = TREE_TYPE (TYPE_VFIELD (current_class_type));
t = build_pointer_type (t);
v_offset = convert (t, current_vtt_parm);
- v_offset = build2 (PLUS_EXPR, t, v_offset,
- BINFO_VPTR_INDEX (derived));
v_offset = build_indirect_ref (v_offset, NULL);
}
else
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 = build1 (NOP_EXPR,
+
+ 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);
TREE_INVARIANT (v_offset) = 1;
offset = convert_to_integer (ptrdiff_type_node,
- size_diffop (offset,
+ size_diffop (offset,
BINFO_OFFSET (v_binfo)));
if (!integer_zerop (offset))
build2 (EQ_EXPR, boolean_type_node,
current_in_charge_parm, integer_zero_node),
v_offset,
- BINFO_OFFSET (binfo));
+ convert_to_integer (ptrdiff_type_node,
+ BINFO_OFFSET (binfo)));
else
offset = v_offset;
}
- target_type = code == PLUS_EXPR ? BINFO_TYPE (binfo) : BINFO_TYPE (d_binfo);
-
target_type = cp_build_qualified_type
(target_type, cp_type_quals (TREE_TYPE (TREE_TYPE (expr))));
ptr_target_type = build_pointer_type (target_type);
if (want_pointer)
target_type = ptr_target_type;
-
+
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);
if (d_binfo == NULL_TREE)
{
tree temp;
-
+
gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type);
-
+
/* 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. */
+ into `(*(a ? &b : &c)).x', and so on. A COND_EXPR is only
+ 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);
cp_build_qualified_type (type, type_quals),
expr, field, NULL_TREE);
expr = fold_if_not_in_template (expr);
-
+
/* Mark the expression const or volatile, as appropriate.
Even though we've dealt with the type above, we still have
to mark the expression itself. */
TREE_READONLY (expr) = 1;
if (type_quals & TYPE_QUAL_VOLATILE)
TREE_THIS_VOLATILE (expr) = 1;
-
+
return expr;
}
object_type = TREE_TYPE (object);
binfo = lookup_base (object_type, type,
- check_access ? ba_check : ba_unique,
+ check_access ? ba_check : ba_unique,
NULL);
if (!binfo || binfo == error_mark_node)
return error_mark_node;
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;
if (!vtbl)
vtbl = build_vfield_ref (instance, basetype);
-
+
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
return mangle_vtbl_for_type (type);
}
-/* Return an IDENTIFIER_NODE for the name of the virtual table table
- for TYPE. */
-
-tree
-get_vtt_name (tree type)
-{
- return mangle_vtt_for_type (type);
-}
-
/* DECL is an entity associated with TYPE, like a virtual table or an
implicitly generated constructor. Determine whether or not DECL
should have external or internal linkage at the object file
is rather important that such things be ignored because any
effort to actually generate DWARF for them will run into
trouble when/if we encounter code like:
-
+
#pragma interface
struct S { virtual void member (); };
-
+
because the artificial declaration of the vtable itself (as
manufactured by the g++ front end) will say that the vtable is
a static member of `S' but only *after* the debug output for
impossible to actually build the vtable, but is useful to get at those
which are known to exist in the runtime. */
-tree
+tree
get_vtable_decl (tree type, int complete)
{
tree decl;
if (CLASSTYPE_VTABLES (type))
return CLASSTYPE_VTABLES (type);
-
+
decl = build_vtable (type, get_vtable_name (type), vtbl_type_node);
CLASSTYPE_VTABLES (type) = decl;
if (complete)
{
DECL_EXTERNAL (decl) = 1;
- cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
+ finish_decl (decl, NULL_TREE, NULL_TREE);
}
return decl;
tree virtuals;
decl = get_vtable_decl (type, /*complete=*/0);
-
+
if (binfo)
{
if (BINFO_NEW_VTABLE_MARKED (binfo))
/* We have already created a vtable for this base, so there's
no need to do it again. */
return 0;
-
+
virtuals = copy_list (BINFO_VIRTUALS (binfo));
TREE_TYPE (decl) = TREE_TYPE (get_vtbl_decl_for_binfo (binfo));
DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (decl));
/* Remember that we've created a vtable for this BINFO, so that we
don't try to do so again. */
SET_BINFO_NEW_VTABLE_MARKED (binfo);
-
+
/* Make fresh virtual list, so we can smash it later. */
BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
static void
modify_vtable_entry (tree t,
- tree binfo,
- tree fndecl,
- tree delta,
- tree *virtuals)
+ tree binfo,
+ tree fndecl,
+ tree delta,
+ tree *virtuals)
{
tree v;
}
\f
-/* Add method METHOD to class TYPE. */
+/* Add method METHOD to class TYPE. If USING_DECL is non-null, it is
+ the USING_DECL naming METHOD. Returns true if the method could be
+ added to the method vec. */
-void
-add_method (tree type, tree method)
+bool
+add_method (tree type, tree method, tree using_decl)
{
- int using;
unsigned slot;
tree overload;
bool template_conv_p = false;
bool complete_p;
bool insert_p = false;
tree current_fns;
+ tree fns;
if (method == error_mark_node)
- return;
+ return false;
complete_p = COMPLETE_TYPE_P (type);
- using = (DECL_CONTEXT (method) != type);
conv_p = DECL_CONV_FN_P (method);
if (conv_p)
template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
CLASSTYPE_METHOD_VEC (type) = method_vec;
}
+ /* Maintain TYPE_HAS_CONSTRUCTOR, etc. */
+ grok_special_member_properties (method);
+
/* Constructors and destructors go in special slots. */
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
slot = CLASSTYPE_CONSTRUCTOR_SLOT;
else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
{
slot = CLASSTYPE_DESTRUCTOR_SLOT;
-
+
if (TYPE_FOR_JAVA (type))
{
if (!DECL_ARTIFICIAL (method))
insert_p = true;
/* See if we already have an entry with this name. */
- for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
VEC_iterate (tree, method_vec, slot, m);
++slot)
{
}
}
current_fns = insert_p ? NULL_TREE : VEC_index (tree, method_vec, slot);
-
- if (processing_template_decl)
- /* TYPE is a template class. Don't issue any errors now; wait
- until instantiation time to complain. */
- ;
- else
+
+ /* Check to see if we've already got this method. */
+ for (fns = current_fns; fns; fns = OVL_NEXT (fns))
{
- tree fns;
+ tree fn = OVL_CURRENT (fns);
+ tree fn_type;
+ tree method_type;
+ tree parms1;
+ tree parms2;
- /* Check to see if we've already got this method. */
- for (fns = current_fns; fns; fns = OVL_NEXT (fns))
- {
- tree fn = OVL_CURRENT (fns);
- tree parms1;
- tree parms2;
- bool same = 1;
+ if (TREE_CODE (fn) != TREE_CODE (method))
+ continue;
- if (TREE_CODE (fn) != TREE_CODE (method))
- continue;
+ /* [over.load] Member function declarations with the
+ same name and the same parameter types cannot be
+ overloaded if any of them is a static member
+ function declaration.
+
+ [namespace.udecl] When a using-declaration brings names
+ from a base class into a derived class scope, member
+ functions in the derived class override and/or hide member
+ functions with the same name and parameter types in a base
+ class (rather than conflicting). */
+ fn_type = TREE_TYPE (fn);
+ method_type = TREE_TYPE (method);
+ parms1 = TYPE_ARG_TYPES (fn_type);
+ parms2 = TYPE_ARG_TYPES (method_type);
+
+ /* Compare the quals on the 'this' parm. Don't compare
+ the whole types, as used functions are treated as
+ coming from the using class in overload resolution. */
+ if (! DECL_STATIC_FUNCTION_P (fn)
+ && ! DECL_STATIC_FUNCTION_P (method)
+ && (TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms1)))
+ != TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms2)))))
+ continue;
+
+ /* For templates, the return type and template parameters
+ must be identical. */
+ if (TREE_CODE (fn) == TEMPLATE_DECL
+ && (!same_type_p (TREE_TYPE (fn_type),
+ TREE_TYPE (method_type))
+ || !comp_template_parms (DECL_TEMPLATE_PARMS (fn),
+ DECL_TEMPLATE_PARMS (method))))
+ continue;
+
+ if (! DECL_STATIC_FUNCTION_P (fn))
+ parms1 = TREE_CHAIN (parms1);
+ if (! DECL_STATIC_FUNCTION_P (method))
+ parms2 = TREE_CHAIN (parms2);
- /* [over.load] Member function declarations with the
- same name and the same parameter types cannot be
- overloaded if any of them is a static member
- function declaration.
-
- [namespace.udecl] When a using-declaration brings names
- from a base class into a derived class scope, member
- functions in the derived class override and/or hide member
- functions with the same name and parameter types in a base
- class (rather than conflicting). */
- parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
- parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
-
- /* Compare the quals on the 'this' parm. Don't compare
- the whole types, as used functions are treated as
- coming from the using class in overload resolution. */
- if (! DECL_STATIC_FUNCTION_P (fn)
- && ! DECL_STATIC_FUNCTION_P (method)
- && (TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms1)))
- != TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms2)))))
- same = 0;
-
- /* For templates, the template parms must be identical. */
- if (TREE_CODE (fn) == TEMPLATE_DECL
- && !comp_template_parms (DECL_TEMPLATE_PARMS (fn),
- DECL_TEMPLATE_PARMS (method)))
- same = 0;
-
- if (! DECL_STATIC_FUNCTION_P (fn))
- parms1 = TREE_CHAIN (parms1);
- if (! DECL_STATIC_FUNCTION_P (method))
- parms2 = TREE_CHAIN (parms2);
-
- if (same && compparms (parms1, parms2)
- && (!DECL_CONV_FN_P (fn)
- || same_type_p (TREE_TYPE (TREE_TYPE (fn)),
- TREE_TYPE (TREE_TYPE (method)))))
+ if (compparms (parms1, parms2)
+ && (!DECL_CONV_FN_P (fn)
+ || same_type_p (TREE_TYPE (fn_type),
+ TREE_TYPE (method_type))))
+ {
+ if (using_decl)
{
- if (using && DECL_CONTEXT (fn) == type)
+ if (DECL_CONTEXT (fn) == type)
/* Defer to the local function. */
- return;
+ return false;
+ if (DECL_CONTEXT (fn) == DECL_CONTEXT (method))
+ error ("repeated using declaration %q+D", using_decl);
else
- {
- cp_error_at ("%q#D and %q#D cannot be overloaded",
- method, fn);
-
- /* We don't call duplicate_decls here to merge
- the declarations because that will confuse
- things if the methods have inline
- definitions. In particular, we will crash
- while processing the definitions. */
- return;
- }
+ error ("using declaration %q+D conflicts with a previous using declaration",
+ using_decl);
}
+ else
+ {
+ error ("%q+#D cannot be overloaded", method);
+ error ("with %q+#D", fn);
+ }
+
+ /* We don't call duplicate_decls here to merge the
+ declarations because that will confuse things if the
+ methods have inline definitions. In particular, we
+ will crash while processing the definitions. */
+ return false;
}
}
- /* Add the new binding. */
+ /* A class should never have more than one destructor. */
+ if (current_fns && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
+ return false;
+
+ /* Add the new binding. */
overload = build_overload (method, current_fns);
-
- if (!conv_p && slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
+
+ if (conv_p)
+ TYPE_HAS_CONVERSION (type) = 1;
+ else if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
push_class_level_binding (DECL_NAME (method), overload);
if (insert_p)
{
+ bool reallocated;
+
/* We only expect to add few methods in the COMPLETE_P case, so
just make room for one more method in that case. */
- if (VEC_reserve (tree, gc, method_vec, complete_p ? -1 : 1))
+ if (complete_p)
+ reallocated = VEC_reserve_exact (tree, gc, method_vec, 1);
+ else
+ reallocated = VEC_reserve (tree, gc, method_vec, 1);
+ if (reallocated)
CLASSTYPE_METHOD_VEC (type) = method_vec;
if (slot == VEC_length (tree, method_vec))
VEC_quick_push (tree, method_vec, overload);
else
/* Replace the current slot. */
VEC_replace (tree, method_vec, slot, overload);
+ return true;
}
/* Subroutines of finish_struct. */
if (TREE_VALUE (elem) != access)
{
if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL)
- cp_error_at ("conflicting access specifications for method"
- " %qD, ignored", TREE_TYPE (fdecl));
+ error ("conflicting access specifications for method"
+ " %q+D, ignored", TREE_TYPE (fdecl));
else
error ("conflicting access specifications for field %qE, ignored",
DECL_NAME (fdecl));
}
else
{
- perform_or_defer_access_check (TYPE_BINFO (t), fdecl);
+ perform_or_defer_access_check (TYPE_BINFO (t), fdecl, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
static void
handle_using_decl (tree using_decl, tree t)
{
- tree ctype = DECL_INITIAL (using_decl);
+ tree decl = USING_DECL_DECLS (using_decl);
tree name = DECL_NAME (using_decl);
tree access
= TREE_PRIVATE (using_decl) ? access_private_node
: TREE_PROTECTED (using_decl) ? access_protected_node
: access_public_node;
- tree fdecl, binfo;
tree flist = NULL_TREE;
tree old_value;
- if (ctype == error_mark_node)
- return;
-
- binfo = lookup_base (t, ctype, ba_any, NULL);
- if (! binfo)
- {
- location_t saved_loc = input_location;
-
- input_location = DECL_SOURCE_LOCATION (using_decl);
- error_not_base_type (ctype, t);
- input_location = saved_loc;
- return;
- }
-
- if (constructor_name_p (name, ctype))
- {
- cp_error_at ("%qD names constructor", using_decl);
- return;
- }
- if (constructor_name_p (name, t))
- {
- cp_error_at ("%qD invalid in %qT", using_decl, t);
- return;
- }
-
- fdecl = lookup_member (binfo, name, 0, false);
-
- if (!fdecl)
- {
- cp_error_at ("no members matching %qD in %q#T", using_decl, ctype);
- return;
- }
-
- if (BASELINK_P (fdecl))
- /* Ignore base type this came from. */
- fdecl = BASELINK_FUNCTIONS (fdecl);
+ gcc_assert (!processing_template_decl && decl);
old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false);
if (old_value)
old_value = NULL_TREE;
}
- if (is_overloaded_fn (fdecl))
- flist = fdecl;
+ cp_emit_debug_info_for_using (decl, USING_DECL_SCOPE (using_decl));
+
+ if (is_overloaded_fn (decl))
+ flist = decl;
if (! old_value)
;
the same name already present in the current class. */;
else
{
- cp_error_at ("%qD invalid in %q#T", using_decl, t);
- cp_error_at (" because of local method %q#D with same name",
- OVL_CURRENT (old_value));
+ error ("%q+D invalid in %q#T", using_decl, t);
+ error (" because of local method %q+#D with same name",
+ OVL_CURRENT (old_value));
return;
}
}
else if (!DECL_ARTIFICIAL (old_value))
{
- cp_error_at ("%qD invalid in %q#T", using_decl, t);
- cp_error_at (" because of local member %q#D with same name", old_value);
+ error ("%q+D invalid in %q#T", using_decl, t);
+ error (" because of local member %q+#D with same name", old_value);
return;
}
-
+
/* Make type T see field decl FDECL with access ACCESS. */
if (flist)
for (; flist; flist = OVL_NEXT (flist))
{
- add_method (t, OVL_CURRENT (flist));
+ add_method (t, OVL_CURRENT (flist), using_decl);
alter_access (t, OVL_CURRENT (flist), access);
}
else
- alter_access (t, fdecl, access);
+ alter_access (t, decl, access);
}
\f
/* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P,
static void
check_bases (tree t,
- int* cant_have_const_ctor_p,
- int* no_const_asn_ref_p)
+ int* cant_have_const_ctor_p,
+ int* no_const_asn_ref_p)
{
int i;
int seen_non_virtual_nearly_empty_base_p;
tree basetype = TREE_TYPE (base_binfo);
gcc_assert (COMPLETE_TYPE_P (basetype));
-
+
/* Effective C++ rule 14. We only need to check TYPE_POLYMORPHIC_P
here because the case of virtual functions but non-virtual
dtor is handled in finish_struct_1. */
- if (warn_ecpp && ! TYPE_POLYMORPHIC_P (basetype))
- warning (0, "base class %q#T has a non-virtual destructor", basetype);
+ if (!TYPE_POLYMORPHIC_P (basetype))
+ warning (OPT_Weffc__,
+ "base class %q#T has a non-virtual destructor", basetype);
/* If the base class doesn't have copy constructors or
assignment operators that take const references, then the
/* A lot of properties from the bases also apply to the derived
class. */
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
- TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype);
- TYPE_HAS_COMPLEX_ASSIGN_REF (t)
+ TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype);
- CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
+ CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype);
+ TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (basetype);
}
}
{
tree parent = BINFO_INHERITANCE_CHAIN (base_binfo);
tree parent_primary = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (parent));
-
+
if (parent_primary
&& SAME_BINFO_TYPE_P (BINFO_TYPE (base_binfo),
BINFO_TYPE (parent_primary)))
else
{
tree delta;
-
+
BINFO_PRIMARY_P (this_primary) = 1;
BINFO_INHERITANCE_CHAIN (this_primary) = base_binfo;
-
+
/* A virtual binfo might have been copied from within
- another hierarchy. As we're about to use it as a
- primary base, make sure the offsets match. */
+ another hierarchy. As we're about to use it as a
+ primary base, make sure the offsets match. */
delta = size_diffop (convert (ssizetype,
BINFO_OFFSET (base_binfo)),
convert (ssizetype,
BINFO_OFFSET (this_primary)));
-
+
propagate_binfo_offsets (this_primary, delta);
}
}
/* Remember the first candidate. */
primary = base_binfo;
}
-
+
found:
/* If we've got a primary base, use it. */
if (primary)
{
tree basetype = BINFO_TYPE (primary);
-
+
CLASSTYPE_PRIMARY_BINFO (t) = primary;
if (BINFO_PRIMARY_P (primary))
/* We are stealing a primary base. */
BINFO_INHERITANCE_CHAIN (primary) = type_binfo;
/* A virtual binfo might have been copied from within
- another hierarchy. As we're about to use it as a primary
- base, make sure the offsets match. */
+ another hierarchy. As we're about to use it as a primary
+ base, make sure the offsets match. */
delta = size_diffop (ssize_int (0),
convert (ssizetype, BINFO_OFFSET (primary)));
-
+
propagate_binfo_offsets (primary, delta);
}
-
+
primary = TYPE_BINFO (basetype);
-
+
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
BINFO_VTABLE (type_binfo) = BINFO_VTABLE (primary);
BINFO_VIRTUALS (type_binfo) = BINFO_VIRTUALS (primary);
finish_struct_bits (tree t)
{
tree variants;
-
+
/* Fix up variants (if any). */
for (variants = TYPE_NEXT_VARIANT (t);
variants;
the TYPE_LANG_SPECIFIC component, so they are not shared. */
TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
- TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
TYPE_POLYMORPHIC_P (variants) = TYPE_POLYMORPHIC_P (t);
-
+
TYPE_BINFO (variants) = TYPE_BINFO (t);
/* Copy whatever these are holding today. */
TYPE_VFIELD (variants) = TYPE_VFIELD (t);
TYPE_METHODS (variants) = TYPE_METHODS (t);
TYPE_FIELDS (variants) = TYPE_FIELDS (t);
- TYPE_SIZE (variants) = TYPE_SIZE (t);
- TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (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))
recalculate what's really an abstract virtual at this point (by
looking in the vtables). */
get_pure_virtuals (t);
-
+
/* If this type has a copy constructor or a destructor, force its
mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be
nonzero. This will cause it to be passed by invisible reference
}
/* Issue warnings about T having private constructors, but no friends,
- and so forth.
+ and so forth.
HAS_NONPRIVATE_METHOD is nonzero if T has any non-private methods or
static members. HAS_NONPRIVATE_STATIC_FN is nonzero if T has any
/* We will have warned when the template was declared; there's
no need to warn on every instantiation. */
|| CLASSTYPE_TEMPLATE_INSTANTIATION (t))
- /* There's no reason to even consider warning about this
+ /* There's no reason to even consider warning about this
class. */
return;
-
+
/* We only issue one warning, if more than one applies, because
otherwise, on code like:
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
/* We're not interested in compiler-generated methods; they don't
provide any way to call private members. */
- if (!DECL_ARTIFICIAL (fn))
+ if (!DECL_ARTIFICIAL (fn))
{
if (!TREE_PRIVATE (fn))
{
- if (DECL_STATIC_FUNCTION_P (fn))
+ if (DECL_STATIC_FUNCTION_P (fn))
/* A non-private static member function is just like a
friend; it can create and invoke private member
functions, and be accessed without a class
instance. */
return;
-
+
has_nonprivate_method = 1;
/* Keep searching for a static member function. */
}
else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn))
has_member_fn = 1;
- }
+ }
- if (!has_nonprivate_method && has_member_fn)
+ if (!has_nonprivate_method && has_member_fn)
{
/* There are no non-private methods, and there's at least one
private member function that isn't a constructor or
constructors/destructors.) */
unsigned i;
tree binfo = TYPE_BINFO (t);
-
+
for (i = 0; i != BINFO_N_BASE_BINFOS (binfo); i++)
if (BINFO_BASE_ACCESS (binfo, i) != access_private_node)
{
has_nonprivate_method = 1;
break;
}
- if (!has_nonprivate_method)
+ if (!has_nonprivate_method)
{
- warning (0, "all member functions in class %qT are private", t);
+ warning (OPT_Wctor_dtor_privacy,
+ "all member functions in class %qT are private", t);
return;
}
}
fn = CLASSTYPE_DESTRUCTORS (t);
if (fn && TREE_PRIVATE (fn))
{
- warning (0, "%q#T only defines a private destructor and has no friends",
+ warning (OPT_Wctor_dtor_privacy,
+ "%q#T only defines a private destructor and has no friends",
t);
return;
}
- if (TYPE_HAS_CONSTRUCTOR (t))
+ if (TYPE_HAS_CONSTRUCTOR (t)
+ /* Implicitly generated constructors are always public. */
+ && (!CLASSTYPE_LAZY_DEFAULT_CTOR (t)
+ || !CLASSTYPE_LAZY_COPY_CTOR (t)))
{
int nonprivate_ctor = 0;
-
+
/* If a non-template class does not define a copy
constructor, one is defined for it, enabling it to avoid
this warning. For a template class, this does not
happen, and so we would normally get a warning on:
- template <class T> class C { private: C(); };
-
+ template <class T> class C { private: C(); };
+
To avoid this asymmetry, we check TYPE_HAS_INIT_REF. All
complete non-template or fully instantiated classes have this
flag set. */
if (!TYPE_HAS_INIT_REF (t))
nonprivate_ctor = 1;
- else
- for (fn = CLASSTYPE_CONSTRUCTORS (t); fn; fn = OVL_NEXT (fn))
+ else
+ for (fn = CLASSTYPE_CONSTRUCTORS (t); fn; fn = OVL_NEXT (fn))
{
tree ctor = OVL_CURRENT (fn);
/* Ideally, we wouldn't count copy constructors (or, in
if (nonprivate_ctor == 0)
{
- warning (0, "%q#T only defines private constructors and has no friends",
- t);
+ warning (OPT_Wctor_dtor_privacy,
+ "%q#T only defines private constructors and has no friends",
+ t);
return;
}
}
static int
method_name_cmp (const void* m1_p, const void* m2_p)
{
- const tree *const m1 = m1_p;
- const tree *const m2 = m2_p;
-
+ const tree *const m1 = (const tree *) m1_p;
+ const tree *const m2 = (const tree *) m2_p;
+
if (*m1 == NULL_TREE && *m2 == NULL_TREE)
return 0;
if (*m1 == NULL_TREE)
static int
resort_method_name_cmp (const void* m1_p, const void* m2_p)
{
- const tree *const m1 = m1_p;
- const tree *const m2 = m2_p;
+ const tree *const m1 = (const tree *) m1_p;
+ const tree *const m2 = (const tree *) m2_p;
if (*m1 == NULL_TREE && *m2 == NULL_TREE)
return 0;
if (*m1 == NULL_TREE)
/* Resort TYPE_METHOD_VEC because pointers have been reordered. */
-void
+void
resort_type_method_vec (void* obj,
- void* orig_obj ATTRIBUTE_UNUSED ,
- gt_pointer_operator new_value,
- void* cookie)
+ void* orig_obj ATTRIBUTE_UNUSED ,
+ gt_pointer_operator new_value,
+ void* cookie)
{
VEC(tree,gc) *method_vec = (VEC(tree,gc) *) obj;
int len = VEC_length (tree, method_vec);
len = VEC_length (tree, method_vec);
/* Clear DECL_IN_AGGR_P for all functions. */
- for (fn_fields = TYPE_METHODS (t); fn_fields;
+ for (fn_fields = TYPE_METHODS (t); fn_fields;
fn_fields = TREE_CHAIN (fn_fields))
DECL_IN_AGGR_P (fn_fields) = 0;
}
/* 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
tree atype;
tree vtable;
- atype = build_cplus_array_type (vtable_entry_type,
+ atype = build_cplus_array_type (vtable_entry_type,
build_index_type (size_int (n - 1)));
layout_type (atype);
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. */
/* Returns TRUE if DERIVED is a binfo containing the binfo BASE as a
subobject. */
-
+
static bool
base_derived_from (tree derived, tree base)
{
Returns true if an overrider was found; false otherwise. */
static bool
-dfs_find_final_overrider_1 (tree binfo,
+dfs_find_final_overrider_1 (tree binfo,
find_final_overrider_data *ffod,
unsigned depth)
{
if (method)
{
tree *candidate = &ffod->candidates;
-
+
/* Remove any candidates overridden by this new function. */
while (*candidate)
{
else
candidate = &TREE_CHAIN (*candidate);
}
-
+
/* Add the new function. */
ffod->candidates = tree_cons (method, binfo, ffod->candidates);
return true;
struct T { virtual void f (); };
struct U : public S, public T { };
- even though calling `f' in `U' is ambiguous. But,
+ even though calling `f' in `U' is ambiguous. But,
struct R { virtual void f(); };
struct S : virtual public R { virtual void f (); };
struct U : public S, public T { };
is not -- there's no way to decide whether to put `S::f' or
- `T::f' in the vtable for `R'.
-
+ `T::f' in the vtable for `R'.
+
The solution is to look at all paths to BINFO. If we find
different overriders along any two, then there is a problem. */
if (DECL_THUNK_P (fn))
dfs_find_final_overrider_post, &ffod);
VEC_free (tree, heap, ffod.path);
-
+
/* If there was no winner, issue an error message. */
if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
- {
- error ("no unique final overrider for %qD in %qT", fn,
- BINFO_TYPE (derived));
- return error_mark_node;
- }
+ return error_mark_node;
return ffod.candidates;
}
/* Find the final overrider. */
overrider = find_final_overrider (TYPE_BINFO (t), b, target_fn);
if (overrider == error_mark_node)
- return;
+ {
+ error ("no unique final overrider for %qD in %qT", target_fn, t);
+ return;
+ }
overrider_target = overrider_fn = TREE_PURPOSE (overrider);
-
+
/* Check for adjusting covariant return types. */
over_return = TREE_TYPE (TREE_TYPE (overrider_target));
base_return = TREE_TYPE (TREE_TYPE (target_fn));
-
+
if (POINTER_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)))
+ && CLASS_TYPE_P (TREE_TYPE (base_return))
+ /* If the overrider is invalid, don't even try. */
+ && !DECL_INVALID_OVERRIDER_P (overrider_target))
{
/* If FN is a covariant thunk, we must figure out the adjustment
- to the final base FN was converting to. As OVERRIDER_TARGET might
- also be converting to the return type of FN, we have to
- combine the two conversions here. */
+ to the final base FN was converting to. As OVERRIDER_TARGET might
+ also be converting to the return type of FN, we have to
+ combine the two conversions here. */
tree fixed_offset, virtual_offset;
over_return = TREE_TYPE (over_return);
base_return = TREE_TYPE (base_return);
-
+
if (DECL_THUNK_P (fn))
{
gcc_assert (DECL_RESULT_THUNK_P (fn));
if (SAME_BINFO_TYPE_P (BINFO_TYPE (thunk_binfo),
BINFO_TYPE (base_binfo)))
break;
-
+
/* See if virtual inheritance is involved. */
for (virtual_offset = thunk_binfo;
virtual_offset;
virtual_offset = BINFO_INHERITANCE_CHAIN (virtual_offset))
if (BINFO_VIRTUAL_P (virtual_offset))
break;
-
+
if (virtual_offset
|| (thunk_binfo && !BINFO_OFFSET_ZEROP (thunk_binfo)))
{
fixed_offset = offset;
}
}
-
+
if (fixed_offset || virtual_offset)
/* Replace the overriding function with a covariant thunk. We
will emit the overriding function in its own slot as
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. */
virtual_base = NULL_TREE;
if (overrider_fn != overrider_target && !virtual_base)
{
/* The ABI specifies that a covariant thunk includes a mangling
- for a this pointer adjustment. This-adjusting thunks that
- override a function from a virtual base have a vcall
- adjustment. When the virtual base in question is a primary
- virtual base, we know the adjustments are zero, (and in the
- non-covariant case, we would not use the thunk).
- Unfortunately we didn't notice this could happen, when
- designing the ABI and so never mandated that such a covariant
- thunk should be emitted. Because we must use the ABI mandated
- name, we must continue searching from the binfo where we
- found the most recent definition of the function, towards the
- primary binfo which first introduced the function into the
- vtable. If that enters a virtual base, we must use a vcall
- this-adjusting thunk. Bleah! */
+ for a this pointer adjustment. This-adjusting thunks that
+ override a function from a virtual base have a vcall
+ adjustment. When the virtual base in question is a primary
+ virtual base, we know the adjustments are zero, (and in the
+ non-covariant case, we would not use the thunk).
+ Unfortunately we didn't notice this could happen, when
+ designing the ABI and so never mandated that such a covariant
+ thunk should be emitted. Because we must use the ABI mandated
+ name, we must continue searching from the binfo where we
+ found the most recent definition of the function, towards the
+ primary binfo which first introduced the function into the
+ vtable. If that enters a virtual base, we must use a vcall
+ this-adjusting thunk. Bleah! */
tree probe = first_defn;
while ((probe = get_primary_binfo (probe))
&& (unsigned) list_length (BINFO_VIRTUALS (probe)) > ix)
if (BINFO_VIRTUAL_P (probe))
virtual_base = probe;
-
+
if (virtual_base)
/* Even if we find a virtual base, the correct delta is
between the overrider and the binfo we're building a vtable
for. */
goto virtual_covariant;
}
-
+
/* Compute the constant adjustment to the `this' pointer. The
`this' pointer, when this function is called, will point at BINFO
(or one of its primary bases, which are at the same offset). */
modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
if (virtual_base)
- BV_VCALL_INDEX (*virtuals)
+ BV_VCALL_INDEX (*virtuals)
= get_vcall_index (overrider_target, BINFO_TYPE (virtual_base));
else
BV_VCALL_INDEX (*virtuals) = NULL_TREE;
/* A base without a vtable needs no modification, and its bases
are uninteresting. */
return dfs_skip_bases;
-
+
if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), t)
&& !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
/* Don't do the primary vtable, if it's new. */
return NULL_TREE;
make_new_vtable (t, binfo);
-
+
/* Now, go through each of the virtual functions in the virtual
function table for BINFO. Find the final overrider, and update
the BINFO_VIRTUALS list appropriately. */
virtuals;
ix++, virtuals = TREE_CHAIN (virtuals),
old_virtuals = TREE_CHAIN (old_virtuals))
- update_vtable_entry_for_fn (t,
- binfo,
+ update_vtable_entry_for_fn (t,
+ binfo,
BV_FN (old_virtuals),
&virtuals, ix);
if (TREE_CODE (decl) == TEMPLATE_DECL)
/* In [temp.mem] we have:
- A specialization of a member function template does not
- override a virtual function from a base class. */
+ A specialization of a member function template does not
+ override a virtual function from a base class. */
return;
if ((DECL_DESTRUCTOR_P (decl)
|| IDENTIFIER_VIRTUAL_P (DECL_NAME (decl))
/* Warn about hidden virtual functions that are not overridden in t.
We know that constructors and destructors don't apply. */
-void
+static void
warn_hidden (tree t)
{
VEC(tree,gc) *method_vec = CLASSTYPE_METHOD_VEC (t);
size_t i;
/* We go through each separately named virtual function. */
- for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
VEC_iterate (tree, method_vec, i, fns);
++i)
{
if (DECL_VINDEX (fndecl))
{
tree *prev = &base_fndecls;
-
- while (*prev)
+
+ while (*prev)
/* If the method from the base class has the same
signature as the method from the derived class, it
has been overridden. */
/* Now give a warning for all base functions without overriders,
as they are hidden. */
- while (base_fndecls)
+ while (base_fndecls)
{
/* Here we know it is a hider, and no overrider exists. */
- cp_warning_at ("%qD was hidden", TREE_VALUE (base_fndecls));
- cp_warning_at (" by %qD", 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))
{
though, so we explicitly tolerate that. We use
TYPE_ANONYMOUS_P rather than ANON_AGGR_TYPE_P so that
we also allow unnamed types used for defining fields. */
- if (DECL_ARTIFICIAL (elt)
+ if (DECL_ARTIFICIAL (elt)
&& (!DECL_IMPLICIT_TYPEDEF_P (elt)
|| TYPE_ANONYMOUS_P (TREE_TYPE (elt))))
continue;
if (TREE_CODE (elt) != FIELD_DECL)
{
- cp_pedwarn_at ("%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))
- cp_pedwarn_at ("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))
- cp_pedwarn_at ("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);
will be used later during class template instantiation.
When FRIEND_P is zero, T can be a static member data (VAR_DECL),
a non-static member data (FIELD_DECL), a member function
- (FUNCTION_DECL), a nested type (RECORD_TYPE, ENUM_TYPE),
+ (FUNCTION_DECL), a nested type (RECORD_TYPE, ENUM_TYPE),
a typedef (TYPE_DECL) or a member class template (TEMPLATE_DECL)
When FRIEND_P is nonzero, T is either a friend class
(RECORD_TYPE, TEMPLATE_DECL) or a friend function
a const reference, respectively. */
static void
-add_implicitly_declared_members (tree t,
+add_implicitly_declared_members (tree t,
int cant_have_const_cctor,
int cant_have_const_assignment)
{
}
/* If we can't get away with being lazy, generate the destructor
- now. */
+ now. */
if (!lazy_p)
lazily_declare_fn (sfk_destructor, t);
}
/* 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);
- tree w = NULL_TREE;
+ tree w;
+
+ /* Extract the declared width of the bitfield, which has been
+ temporarily stashed in DECL_INITIAL. */
+ w = DECL_INITIAL (field);
+ gcc_assert (w != NULL_TREE);
+ /* Remove the bit-field width indicator so that the rest of the
+ compiler does not treat that value as an initializer. */
+ DECL_INITIAL (field) = NULL_TREE;
/* Detect invalid bit-field type. */
- if (DECL_INITIAL (field)
- && ! INTEGRAL_TYPE_P (TREE_TYPE (field)))
+ if (!INTEGRAL_TYPE_P (type))
{
- cp_error_at ("bit-field %q#D with non-integral type", field);
+ error ("bit-field %q+#D with non-integral type", field);
w = error_mark_node;
}
-
- /* Detect and ignore out of range field width. */
- if (DECL_INITIAL (field))
+ else
{
- w = DECL_INITIAL (field);
-
/* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
STRIP_NOPS (w);
if (TREE_CODE (w) != INTEGER_CST)
{
- cp_error_at ("bit-field %qD width not an integer constant",
- field);
+ error ("bit-field %q+D width not an integer constant", field);
w = error_mark_node;
}
else if (tree_int_cst_sgn (w) < 0)
{
- cp_error_at ("negative width in bit-field %qD", field);
+ error ("negative width in bit-field %q+D", field);
w = error_mark_node;
}
else if (integer_zerop (w) && DECL_NAME (field) != 0)
{
- cp_error_at ("zero width for bit-field %qD", field);
+ error ("zero width for bit-field %q+D", field);
w = error_mark_node;
}
else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0
&& TREE_CODE (type) != ENUMERAL_TYPE
&& TREE_CODE (type) != BOOLEAN_TYPE)
- cp_warning_at ("width of %qD exceeds its type", field);
+ 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),
min_precision
(TYPE_MAX_VALUE (type),
TYPE_UNSIGNED (type)))))
- cp_warning_at ("%qD is too small to hold all values of %q#T",
- field, type);
+ warning (0, "%q+D is too small to hold all values of %q#T", field, type);
}
-
- /* Remove the bit-field width indicator so that the rest of the
- compiler does not treat that value as an initializer. */
- DECL_INITIAL (field) = NULL_TREE;
if (w != error_mark_node)
{
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;
}
}
static void
check_field_decl (tree field,
- tree t,
- int* cant_have_const_ctor,
- int* no_const_asn_ref,
+ tree t,
+ int* cant_have_const_ctor,
+ int* no_const_asn_ref,
int* any_default_members)
{
tree type = strip_array_types (TREE_TYPE (field));
/* Never let anything with uninheritable virtuals
make it through without complaint. */
abstract_virtuals_error (field, type);
-
+
if (TREE_CODE (t) == UNION_TYPE)
{
if (TYPE_NEEDS_CONSTRUCTING (type))
- cp_error_at ("member %q#D with constructor not allowed in union",
- field);
+ error ("member %q+#D with constructor not allowed in union",
+ field);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
- cp_error_at ("member %q#D with destructor not allowed in union",
- field);
+ error ("member %q+#D with destructor not allowed in union", field);
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
- cp_error_at ("member %q#D with copy assignment operator not allowed in union",
- field);
+ error ("member %q+#D with copy assignment operator not allowed in union",
+ field);
}
else
{
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
- TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|= 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))
tree *next;
bool has_pointers;
int any_default_members;
+ int cant_pack = 0;
/* Assume there are no access declarations. */
*access_decls = NULL_TREE;
next = &TREE_CHAIN (x);
- if (TREE_CODE (x) == FIELD_DECL)
- {
- if (TYPE_PACKED (t))
- {
- if (!pod_type_p (TREE_TYPE (x)) && !TYPE_PACKED (TREE_TYPE (x)))
- cp_warning_at
- ("ignoring packed attribute on unpacked non-POD field %q#D",
- x);
- else
- DECL_PACKED (x) = 1;
- }
-
- if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
- /* We don't treat zero-width bitfields as making a class
- non-empty. */
- ;
- else
- {
- tree element_type;
-
- /* The class is non-empty. */
- CLASSTYPE_EMPTY_P (t) = 0;
- /* The class is not even nearly empty. */
- CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
- /* If one of the data members contains an empty class,
- so does T. */
- element_type = strip_array_types (type);
- if (CLASS_TYPE_P (element_type)
- && CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type))
- CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
- }
- }
-
if (TREE_CODE (x) == USING_DECL)
{
/* Prune the access declaration from the list of fields. */
reference type, the program is ill-formed. */
if (TREE_CODE (x) == VAR_DECL)
{
- cp_error_at ("%qD may not be static because it is a member of a union", x);
+ error ("%q+D may not be static because it is a member of a union", x);
continue;
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- cp_error_at ("%qD may not have reference type %qT because"
- " it is a member of a union",
- x, type);
+ error ("%q+D may not have reference type %qT 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 %qD in local class cannot be static", x);
-
/* Perform error checking that did not get done in
grokdeclarator. */
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- cp_error_at ("field %qD invalidly declared function type", x);
+ error ("field %q+D invalidly declared function type", x);
type = build_pointer_type (type);
TREE_TYPE (x) = type;
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
- cp_error_at ("field %qD invalidly declared method type", x);
+ error ("field %q+D invalidly declared method type", x);
type = build_pointer_type (type);
TREE_TYPE (x) = type;
}
if (type == error_mark_node)
continue;
-
+
if (TREE_CODE (x) == CONST_DECL || TREE_CODE (x) == VAR_DECL)
continue;
/* If this is of reference type, check if it needs an init.
Also do a little ANSI jig if necessary. */
if (TREE_CODE (type) == REFERENCE_TYPE)
- {
+ {
CLASSTYPE_NON_POD_P (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
&& extra_warnings)
- cp_warning_at ("non-static reference %q#D in class without a constructor", x);
+ warning (OPT_Wextra, "non-static reference %q+#D in class without a constructor", x);
}
type = strip_array_types (type);
+ if (TYPE_PACKED (t))
+ {
+ if (!pod_type_p (type) && !TYPE_PACKED (type))
+ {
+ warning
+ (0,
+ "ignoring packed attribute because of unpacked non-POD field %q+#D",
+ x);
+ cant_pack = 1;
+ }
+ else if (TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
+ DECL_PACKED (x) = 1;
+ }
+
+ if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
+ /* We don't treat zero-width bitfields as making a class
+ non-empty. */
+ ;
+ else
+ {
+ /* The class is non-empty. */
+ CLASSTYPE_EMPTY_P (t) = 0;
+ /* The class is not even nearly empty. */
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ /* If one of the data members contains an empty class,
+ so does T. */
+ if (CLASS_TYPE_P (type)
+ && CLASSTYPE_CONTAINS_EMPTY_CLASS_P (type))
+ CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
+ }
+
/* This is used by -Weffc++ (see below). Warn only for pointers
to members which might hold dynamic memory. So do not warn
for pointers to functions or pointers to members. */
CLASSTYPE_HAS_MUTABLE (t) = 1;
if (! pod_type_p (type))
- /* DR 148 now allows pointers to members (which are POD themselves),
- to be allowed in POD structs. */
+ /* DR 148 now allows pointers to members (which are POD themselves),
+ to be allowed in POD structs. */
CLASSTYPE_NON_POD_P (t) = 1;
if (! zero_init_p (type))
if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
&& extra_warnings)
- cp_warning_at ("non-static const member %q#D in class without a constructor", x);
+ 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))
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))
- cp_pedwarn_at ("field %q#D with same name as class", x);
+ pedwarn ("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,
-- Warn only if there is a non-trivial destructor. We assume that the
user at least implemented the cleanup correctly, and a destructor
is needed to free dynamic memory.
-
+
This seems enough for practical purposes. */
- if (warn_ecpp
- && has_pointers
- && TYPE_HAS_CONSTRUCTOR (t)
- && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
- && !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
- {
- warning (0, "%q#T has pointer data members", t);
-
+ if (warn_ecpp
+ && has_pointers
+ && TYPE_HAS_CONSTRUCTOR (t)
+ && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ && !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
+ {
+ warning (OPT_Weffc__, "%q#T has pointer data members", t);
+
if (! TYPE_HAS_INIT_REF (t))
{
- warning (0, " but does not override %<%T(const %T&)%>", t, t);
- if (! TYPE_HAS_ASSIGN_REF (t))
- warning (0, " or %<operator=(const %T&)%>", t);
+ warning (OPT_Weffc__,
+ " but does not override %<%T(const %T&)%>", t, t);
+ if (!TYPE_HAS_ASSIGN_REF (t))
+ warning (OPT_Weffc__, " or %<operator=(const %T&)%>", t);
}
else if (! TYPE_HAS_ASSIGN_REF (t))
- warning (0, " but does not override %<operator=(const %T&)%>", t);
+ warning (OPT_Weffc__,
+ " but does not override %<operator=(const %T&)%>", t);
}
+ /* If any of the fields couldn't be packed, unset TYPE_PACKED. */
+ if (cant_pack)
+ TYPE_PACKED (t) = 0;
/* Check anonymous struct/anonymous union fields. */
finish_struct_anon (t);
/* Record the location of this empty object in OFFSETS. */
n = splay_tree_lookup (offsets, (splay_tree_key) offset);
if (!n)
- n = splay_tree_insert (offsets,
+ n = splay_tree_insert (offsets,
(splay_tree_key) offset,
(splay_tree_value) NULL_TREE);
- n->value = ((splay_tree_value)
+ n->value = ((splay_tree_value)
tree_cons (NULL_TREE,
type,
(tree) n->value));
is returned. Otherwise, returns zero. */
static int
-walk_subobject_offsets (tree type,
- subobject_offset_fn f,
- tree offset,
- splay_tree offsets,
- tree max_offset,
- int vbases_p)
+walk_subobject_offsets (tree type,
+ subobject_offset_fn f,
+ tree offset,
+ splay_tree offsets,
+ tree max_offset,
+ int vbases_p)
{
int r = 0;
tree type_binfo = NULL_TREE;
if (max_offset && INT_CST_LT (max_offset, offset))
return 0;
- if (!TYPE_P (type))
+ if (type == error_mark_node)
+ return 0;
+
+ if (!TYPE_P (type))
{
if (abi_version_at_least (2))
type_binfo = type;
{
tree binfo_offset;
- if (abi_version_at_least (2)
+ if (abi_version_at_least (2)
&& BINFO_VIRTUAL_P (binfo))
continue;
- if (!vbases_p
- && BINFO_VIRTUAL_P (binfo)
+ if (!vbases_p
+ && BINFO_VIRTUAL_P (binfo)
&& !BINFO_PRIMARY_P (binfo))
continue;
class yet, but the offsets for direct non-virtual
bases can be calculated by going back to the TYPE. */
orig_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), i);
- binfo_offset = size_binop (PLUS_EXPR,
+ binfo_offset = size_binop (PLUS_EXPR,
offset,
BINFO_OFFSET (orig_binfo));
}
binfo_offset,
offsets,
max_offset,
- (abi_version_at_least (2)
+ (abi_version_at_least (2)
? /*vbases_p=*/0 : vbases_p));
if (r)
return r;
virtual. (If it is non-virtual, then it was walked
above.) */
tree vbase = get_primary_binfo (type_binfo);
-
+
if (vbase && BINFO_VIRTUAL_P (vbase)
&& BINFO_PRIMARY_P (vbase)
&& BINFO_INHERITANCE_CHAIN (vbase) == type_binfo)
{
- r = (walk_subobject_offsets
+ r = (walk_subobject_offsets
(vbase, f, offset,
offsets, max_offset, /*vbases_p=*/0));
if (r)
/* Step through each of the elements in the array. */
for (index = size_zero_node;
/* G++ 3.2 had an off-by-one error here. */
- (abi_version_at_least (2)
+ (abi_version_at_least (2)
? !INT_CST_LT (TYPE_MAX_VALUE (domain), index)
: INT_CST_LT (index, TYPE_MAX_VALUE (domain)));
index = size_binop (PLUS_EXPR, index, size_one_node))
/*vbases_p=*/1);
if (r)
return r;
- offset = size_binop (PLUS_EXPR, offset,
+ offset = size_binop (PLUS_EXPR, offset,
TYPE_SIZE_UNIT (TREE_TYPE (type)));
/* If this new OFFSET is bigger than the MAX_OFFSET, then
there's no point in iterating through the remaining
return 0;
}
-/* Record all of the empty subobjects of TYPE (located at OFFSET) in
- OFFSETS. If VBASES_P is nonzero, virtual bases of TYPE are
- examined. */
+/* 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. */
static void
-record_subobject_offsets (tree type,
- tree offset,
- splay_tree offsets,
- int vbases_p)
-{
+record_subobject_offsets (tree type,
+ tree offset,
+ splay_tree offsets,
+ bool is_data_member)
+{
+ 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
+ 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
+ overlap with offsets past the size of the biggest empty class) or
+ at the end of the class.
+
+ However, if we are placing an empty base class, then we must record
+ all offsets, as either the empty class is at offset zero (where
+ 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)))
+ max_offset = sizeof_biggest_empty_class;
+ else
+ max_offset = NULL_TREE;
walk_subobject_offsets (type, record_subobject_offset, offset,
- offsets, /*max_offset=*/NULL_TREE, vbases_p);
+ offsets, max_offset, is_data_member);
}
/* Returns nonzero if any of the empty subobjects of TYPE (located at
static int
layout_conflict_p (tree type,
- tree offset,
- splay_tree offsets,
- int vbases_p)
+ tree offset,
+ splay_tree offsets,
+ int vbases_p)
{
splay_tree_node max_node;
the position of the DECL. */
static void
-layout_nonempty_base_or_field (record_layout_info rli,
- tree decl,
- tree binfo,
+layout_nonempty_base_or_field (record_layout_info rli,
+ tree decl,
+ tree binfo,
splay_tree offsets)
{
tree offset = NULL_TREE;
bool field_p;
tree type;
-
+
if (binfo)
{
/* For the purposes of determining layout conflicts, we want to
/* We have to check to see whether or not there is already
something of the same type at the offset we're about to use.
For example, consider:
-
+
struct S {};
struct T : public S { int i; };
struct U : public S, public T {};
-
+
Here, we put S at offset zero in U. Then, we can't put T at
offset zero -- its S component would be at the same address
as the S we already allocated. So, we have to skip ahead.
virtual base. */
if (!abi_version_at_least (2) && binfo && BINFO_VIRTUAL_P (binfo))
break;
- if (layout_conflict_p (field_p ? type : binfo, offset,
+ if (layout_conflict_p (field_p ? type : binfo, offset,
offsets, field_p))
{
/* Strip off the size allocated to this field. That puts us
/* Bump up by the alignment required for the type. */
rli->bitpos
- = size_binop (PLUS_EXPR, rli->bitpos,
- bitsize_int (binfo
+ = size_binop (PLUS_EXPR, rli->bitpos,
+ bitsize_int (binfo
? CLASSTYPE_ALIGN (type)
: TYPE_ALIGN (type)));
normalize_rli (rli);
this point because their BINFO_OFFSET is copied from another
hierarchy. Therefore, we may not need to add the entire
OFFSET. */
- propagate_binfo_offsets (binfo,
+ propagate_binfo_offsets (binfo,
size_diffop (convert (ssizetype, offset),
- convert (ssizetype,
+ convert (ssizetype,
BINFO_OFFSET (binfo))));
}
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);
if (abi_version_at_least (2))
propagate_binfo_offsets
(binfo, size_diffop (size_zero_node, BINFO_OFFSET (binfo)));
- else if (warn_abi)
- warning (0, "offset of empty base %qT may not be ABI-compliant and may"
+ else
+ warning (OPT_Wabi,
+ "offset of empty base %qT may not be ABI-compliant and may"
"change in a future version of GCC",
BINFO_TYPE (binfo));
}
-
+
/* This is an empty base class. We first try to put it at offset
zero. */
if (layout_conflict_p (binfo,
BINFO_OFFSET (binfo),
- offsets,
+ 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, convert (ssizetype, eoc));
- while (1)
+ while (1)
{
if (!layout_conflict_p (binfo,
- BINFO_OFFSET (binfo),
+ BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
/* We finally found a spot where there's no overlap. */
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;
}
any base class. OFFSETS gives the location of empty base
subobjects. T is the most derived type. Return nonzero if the new
object cannot be nearly-empty. A new FIELD_DECL is inserted at
- *NEXT_FIELD, unless BINFO is for an empty base class.
+ *NEXT_FIELD, unless BINFO is for an empty base class.
Returns the location at which the next field should be inserted. */
/* This error is now reported in xref_tag, thus giving better
location information. */
return next_field;
-
+
/* Place the base class. */
if (!is_empty_class (basetype))
{
/* The containing class is non-empty because it has a non-empty
base class. */
CLASSTYPE_EMPTY_P (t) = 0;
-
+
/* Create the FIELD_DECL. */
decl = build_decl (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 (atend)
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
- /* The check above (used in G++ 3.2) is insufficient because
+ /* The check above (used in G++ 3.2) is insufficient because
an empty class placed at offset zero might itself have an
empty base at a nonzero offset. */
- else if (walk_subobject_offsets (basetype,
+ else if (walk_subobject_offsets (basetype,
empty_base_at_nonzero_offset_p,
size_zero_node,
/*offsets=*/NULL,
{
if (abi_version_at_least (2))
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
- else if (warn_abi)
- warning (0, "class %qT will be considered nearly empty in a "
+ else
+ warning (OPT_Wabi,
+ "class %qT will be considered nearly empty in a "
"future version of GCC", t);
}
}
-
+
/* We do not create a FIELD_DECL for empty base classes because
it might overlap some other field. We want to be able to
create CONSTRUCTORs for the class by iterating over the
/* Record the offsets of BINFO and its base subobjects. */
record_subobject_offsets (binfo,
BINFO_OFFSET (binfo),
- offsets,
- /*vbases_p=*/0);
+ offsets,
+ /*is_data_member=*/false);
return next_field;
}
{
check_for_override (x, t);
if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x))
- cp_error_at ("initializer specified for non-virtual method %qD", x);
+ error ("initializer specified for non-virtual method %q+D", x);
/* The name of the field is the original field name
Save this in auxiliary field for later overloading. */
if (DECL_VINDEX (x))
parmtypes = TREE_CHAIN (parmtypes);
/* If this is subobject constructor or destructor, add the vtt
parameter. */
- TREE_TYPE (clone)
+ TREE_TYPE (clone)
= 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)
+ TREE_TYPE (clone)
= cp_build_type_attribute_variant (TREE_TYPE (clone),
TYPE_ATTRIBUTES (TREE_TYPE (fn)));
}
/* Create the RTL for this function. */
SET_DECL_RTL (clone, NULL_RTX);
rest_of_decl_compilation (clone, /*top_level=*/1, at_eof);
-
+
/* Make it easy to find the CLONE given the FN. */
TREE_CHAIN (clone) = TREE_CHAIN (fn);
TREE_CHAIN (fn) = clone;
{
tree result;
- DECL_TEMPLATE_RESULT (clone)
+ DECL_TEMPLATE_RESULT (clone)
= build_clone (DECL_TEMPLATE_RESULT (clone), name);
result = DECL_TEMPLATE_RESULT (clone);
DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result));
and a not-in-charge version. */
clone = build_clone (fn, complete_ctor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone);
+ add_method (DECL_CONTEXT (clone), clone, NULL_TREE);
clone = build_clone (fn, base_ctor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone);
+ add_method (DECL_CONTEXT (clone), clone, NULL_TREE);
}
else
{
version. We clone the deleting version first because that
means it will go second on the TYPE_METHODS list -- and that
corresponds to the correct layout order in the virtual
- function table.
+ function table.
- For a non-virtual destructor, we do not build a deleting
+ For a non-virtual destructor, we do not build a deleting
destructor. */
if (DECL_VIRTUAL_P (fn))
{
clone = build_clone (fn, deleting_dtor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone);
+ add_method (DECL_CONTEXT (clone), clone, NULL_TREE);
}
clone = build_clone (fn, complete_dtor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone);
+ add_method (DECL_CONTEXT (clone), clone, NULL_TREE);
clone = build_clone (fn, base_dtor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone);
+ add_method (DECL_CONTEXT (clone), clone, NULL_TREE);
}
/* Note that this is an abstract function that is never emitted. */
adjust_clone_args (tree decl)
{
tree clone;
-
+
for (clone = TREE_CHAIN (decl); clone && DECL_CLONED_FUNCTION (clone);
clone = TREE_CHAIN (clone))
{
tree decl_parms, clone_parms;
clone_parms = orig_clone_parms;
-
+
/* Skip the 'this' parameter. */
orig_clone_parms = TREE_CHAIN (orig_clone_parms);
orig_decl_parms = TREE_CHAIN (orig_decl_parms);
orig_decl_parms = TREE_CHAIN (orig_decl_parms);
if (DECL_HAS_VTT_PARM_P (decl))
orig_decl_parms = TREE_CHAIN (orig_decl_parms);
-
+
clone_parms = orig_clone_parms;
if (DECL_HAS_VTT_PARM_P (clone))
clone_parms = TREE_CHAIN (clone_parms);
-
+
for (decl_parms = orig_decl_parms; decl_parms;
decl_parms = TREE_CHAIN (decl_parms),
clone_parms = TREE_CHAIN (clone_parms))
{
gcc_assert (same_type_p (TREE_TYPE (decl_parms),
TREE_TYPE (clone_parms)));
-
+
if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms))
{
/* A default parameter has been added. Adjust the
if (exceptions)
type = build_exception_variant (type, exceptions);
TREE_TYPE (clone) = type;
-
+
clone_parms = NULL_TREE;
break;
}
{
tree *fieldsp;
- fieldsp = &TYPE_FIELDS (t);
+ fieldsp = &TYPE_FIELDS (t);
while (*fieldsp)
{
if (TREE_CODE (*fieldsp) == FIELD_DECL
- && DECL_C_BIT_FIELD (*fieldsp)
+ && DECL_C_BIT_FIELD (*fieldsp)
&& DECL_INITIAL (*fieldsp))
*fieldsp = TREE_CHAIN (*fieldsp);
else
argument is of type `size_t', then we have to pass the size of
the array to the deallocation function, so we will need to store
a cookie. */
- fns = lookup_fnfields (TYPE_BINFO (type),
+ fns = lookup_fnfields (TYPE_BINFO (type),
ansi_opname (VEC_DELETE_EXPR),
/*protect=*/0);
/* If there are no `operator []' members, or the lookup is
argument is `size_t', it will be the usual deallocation
function -- unless there is one-argument function, too. */
if (TREE_CHAIN (second_parm) == void_list_node
- && same_type_p (TREE_VALUE (second_parm), sizetype))
+ && same_type_p (TREE_VALUE (second_parm), size_type_node))
has_two_argument_delete_p = true;
}
CLASSTYPE_NON_AGGREGATE (t)
|= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_POLYMORPHIC_P (t));
CLASSTYPE_NON_POD_P (t)
- |= (CLASSTYPE_NON_AGGREGATE (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));
/* Synthesize any needed methods. */
add_implicitly_declared_members (t,
&& TREE_CODE (DECL_VINDEX (fn)) != INTEGER_CST)
{
tree new_virtual = make_node (TREE_LIST);
-
+
BV_FN (new_virtual) = fn;
BV_DELTA (new_virtual) = integer_zero_node;
BV_VCALL_INDEX (new_virtual) = NULL_TREE;
TREE_CHAIN (new_virtual) = *virtuals_p;
*virtuals_p = new_virtual;
}
-
+
/* If we couldn't find an appropriate base class, create a new field
here. Even if there weren't any new virtual functions, we might need a
new virtual function table if we're supposed to include vptrs in
the derived class vtable pointer, since they have different
types. Thus, in a derived class destructor, where the base
class constructor was inlined, we could generate bad code for
- setting up the vtable pointer.
+ setting up the vtable pointer.
- Therefore, we use one type for all vtable pointers. We still
+ Therefore, we use one type for all vtable pointers. We still
use a type-correct type; it's just doesn't indicate the array
bounds. That's better than using `void*' or some such; it's
cleaner, and it let's the alias analysis code know that these
tree field;
field = build_decl (FIELD_DECL, get_vfield_name (t), vtbl_ptr_type_node);
- SET_DECL_ASSEMBLER_NAME (field, get_identifier (VFIELD_BASE));
DECL_VIRTUAL_P (field) = 1;
DECL_ARTIFICIAL (field) = 1;
DECL_FIELD_CONTEXT (field) = t;
DECL_FCONTEXT (field) = t;
-
+
TYPE_VFIELD (t) = field;
-
+
/* This class is non-empty. */
CLASSTYPE_EMPTY_P (t) = 0;
/* Update BINFO's offset. */
BINFO_OFFSET (binfo)
- = convert (sizetype,
+ = convert (sizetype,
size_binop (PLUS_EXPR,
convert (ssizetype, BINFO_OFFSET (binfo)),
offset));
if (primary_binfo && BINFO_INHERITANCE_CHAIN (primary_binfo) == binfo)
propagate_binfo_offsets (primary_binfo, offset);
-
+
/* Scan all of the bases, pushing the BINFO_OFFSET adjust
downwards. */
for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
the results which is not particularly tractable. */
if (warn_abi
&& first_vbase
- && (tree_int_cst_lt
+ && (tree_int_cst_lt
(size_binop (CEIL_DIV_EXPR,
round_up (CLASSTYPE_SIZE (t),
CLASSTYPE_ALIGN (basetype)),
bitsize_unit_node),
BINFO_OFFSET (vbase))))
- warning (0, "offset of virtual base %qT is not ABI-compliant and "
- "may change in a future version of GCC",
+ warning (OPT_Wabi,
+ "offset of virtual base %qT is not ABI-compliant and "
+ "may change in a future version of GCC",
basetype);
first_vbase = false;
{
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 there are no repeated bases, nothing can be ambiguous. */
if (!CLASSTYPE_REPEATED_BASE_P (t))
return;
-
+
/* Check direct bases. */
for (binfo = TYPE_BINFO (t), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
VEC_iterate (tree, vbases, i, binfo); i++)
{
basetype = BINFO_TYPE (binfo);
-
+
if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL))
- warning (0, "virtual base %qT inaccessible in %qT due to ambiguity",
+ warning (OPT_Wextra, "virtual base %qT inaccessible in %qT due to ambiguity",
basetype, t);
}
}
because we are willing to overlay multiple bases at the same
offset. However, now we need to make sure that RLI is big enough
to reflect the entire class. */
- eoc = end_of_class (rli->t,
+ eoc = end_of_class (rli->t,
CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
rli_size = rli_size_unit_so_far (rli);
if (TREE_CODE (rli_size) == INTEGER_CST
/* The size should have been rounded to a whole byte. */
gcc_assert (tree_int_cst_equal
(rli->bitpos, round_down (rli->bitpos, BITS_PER_UNIT)));
- rli->bitpos
- = size_binop (PLUS_EXPR,
+ rli->bitpos
+ = size_binop (PLUS_EXPR,
rli->bitpos,
size_binop (MULT_EXPR,
convert (bitsizetype,
next_field = &TYPE_FIELDS (t);
/* Build FIELD_DECLs for all of the non-virtual base-types. */
- empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
+ empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
NULL, NULL);
build_base_fields (rli, empty_base_offsets, next_field);
-
+
/* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field))
{
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);
/* If the static data member has incomplete type, keep track
- of it so that it can be completed later. (The handling
+ of it so that it can be completed later. (The handling
of pending statics in finish_record_layout is
insufficient; consider:
struct S1;
struct S2 { static S1 s1; };
-
- At this point, finish_record_layout will be called, but
+
+ At this point, finish_record_layout will be called, but
S1 is still incomplete.) */
if (TREE_CODE (field) == VAR_DECL)
{
}
type = TREE_TYPE (field);
-
+ if (type == error_mark_node)
+ continue;
+
padding = NULL_TREE;
/* If this field is a bit-field whose width is greater than its
of the field. Then, we are supposed to use the left over
bits as additional padding. */
for (itk = itk_char; itk != itk_none; ++itk)
- if (INT_CST_LT (DECL_SIZE (field),
+ if (INT_CST_LT (DECL_SIZE (field),
TYPE_SIZE (integer_types[itk])))
break;
padding = DECL_SIZE (field);
else
{
- if (warn_abi && TREE_CODE (t) == UNION_TYPE)
- warning (0, "size assigned to %qT may not be "
+ if (TREE_CODE (t) == UNION_TYPE)
+ warning (OPT_Wabi, "size assigned to %qT may not be "
"ABI-compliant and may change in a future "
- "version of GCC",
+ "version of GCC",
t);
padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
TYPE_SIZE (integer_type));
&& DECL_MODE (field) != TYPE_MODE (type))
/* Versions of G++ before G++ 3.4 did not reset the
DECL_MODE. */
- warning (0, "the offset of %qD may not be ABI-compliant and may "
+ warning (OPT_Wabi,
+ "the offset of %qD may not be ABI-compliant and may "
"change in a future version of GCC", field);
}
else
/* Remember the location of any empty classes in FIELD. */
if (abi_version_at_least (2))
- record_subobject_offsets (TREE_TYPE (field),
+ record_subobject_offsets (TREE_TYPE (field),
byte_position(field),
empty_base_offsets,
- /*vbases_p=*/1);
+ /*is_data_member=*/true);
/* 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
comply with the ABI. */
if (warn_abi
- && DECL_C_BIT_FIELD (field)
+ && DECL_C_BIT_FIELD (field)
+ /* The TREE_NO_WARNING flag gets set by Objective-C when
+ laying out an Objective-C class. The ObjC ABI differs
+ from the C++ ABI, and so we do not want a warning
+ here. */
+ && !TREE_NO_WARNING (field)
&& !last_field_was_bitfield
&& !integer_zerop (size_binop (TRUNC_MOD_EXPR,
DECL_FIELD_BIT_OFFSET (field),
bitsize_unit_node)))
- cp_warning_at ("offset of %qD is not ABI-compliant and may "
- "change in a future version of GCC",
- field);
+ warning (OPT_Wabi, "offset of %q+D is not ABI-compliant and may "
+ "change in a future version of GCC", field);
/* G++ used to use DECL_FIELD_OFFSET as if it were the byte
offset of the field. */
- if (warn_abi
+ if (warn_abi
&& !tree_int_cst_equal (DECL_FIELD_OFFSET (field),
byte_position (field))
&& contains_empty_class_p (TREE_TYPE (field)))
- cp_warning_at ("%qD contains empty classes which may cause base "
- "classes to be placed at different locations in a "
- "future version of GCC",
- field);
+ warning (OPT_Wabi, "%q+D contains empty classes which may cause base "
+ "classes to be placed at different locations in a "
+ "future version of GCC", field);
+
+ /* The middle end uses the type of expressions to determine the
+ possible range of expression values. In order to optimize
+ "x.i > 7" to "false" for a 2-bit bitfield "i", the middle end
+ must be made aware of the width of "i", via its type.
+
+ Because C++ does not have integer types of arbitrary width,
+ we must (for the purposes of the front end) convert from the
+ type assigned here to the declared type of the bitfield
+ whenever a bitfield expression is used as an rvalue.
+ Similarly, when assigning a value to a bitfield, the value
+ 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);
+ 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));
+ }
/* If we needed additional padding after this field, add it
now. */
{
tree padding_field;
- padding_field = build_decl (FIELD_DECL,
+ padding_field = build_decl (FIELD_DECL,
NULL_TREE,
- char_type_node);
+ char_type_node);
DECL_BIT_FIELD (padding_field) = 1;
DECL_SIZE (padding_field) = padding;
DECL_CONTEXT (padding_field) = t;
DECL_ARTIFICIAL (padding_field) = 1;
DECL_IGNORED_P (padding_field) = 1;
layout_nonempty_base_or_field (rli, padding_field,
- NULL_TREE,
+ NULL_TREE,
empty_base_offsets);
}
if (CLASSTYPE_NON_POD_P (t) || CLASSTYPE_EMPTY_P (t))
{
base_t = make_node (TREE_CODE (t));
-
+
/* Set the size and alignment for the new type. In G++ 3.2, all
empty classes were considered to have size zero when used as
base classes. */
TYPE_SIZE (base_t) = bitsize_zero_node;
TYPE_SIZE_UNIT (base_t) = size_zero_node;
if (warn_abi && !integer_zerop (rli_size_unit_so_far (rli)))
- warning (0, "layout of classes derived from empty class %qT "
+ warning (OPT_Wabi,
+ "layout of classes derived from empty class %qT "
"may change in a future version of GCC",
t);
}
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)
+ TYPE_SIZE_UNIT (base_t)
= size_binop (MAX_EXPR,
convert (sizetype,
size_binop (CEIL_DIV_EXPR,
rli_size_so_far (rli),
bitsize_int (BITS_PER_UNIT))),
eoc);
- TYPE_SIZE (base_t)
+ TYPE_SIZE (base_t)
= size_binop (MAX_EXPR,
rli_size_so_far (rli),
size_binop (MULT_EXPR,
if (TREE_CODE (field) == FIELD_DECL)
{
*next_field = build_decl (FIELD_DECL,
- DECL_NAME (field),
+ DECL_NAME (field),
TREE_TYPE (field));
DECL_CONTEXT (*next_field) = base_t;
DECL_FIELD_OFFSET (*next_field) = DECL_FIELD_OFFSET (field);
base subobject fields. */
layout_virtual_bases (rli, empty_base_offsets);
- /* Make sure that empty classes are reflected in RLI at this
+ /* Make sure that empty classes are reflected in RLI at this
point. */
include_empty_classes(rli);
/* 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,
+ 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. */
/* Clean up. */
splay_tree_delete (empty_base_offsets);
+
+ if (CLASSTYPE_EMPTY_P (t)
+ && tree_int_cst_lt (sizeof_biggest_empty_class,
+ TYPE_SIZE_UNIT (t)))
+ sizeof_biggest_empty_class = TYPE_SIZE_UNIT (t);
}
/* Determine the "key method" for the class type indicated by TYPE,
CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
fixup_inline_methods (t);
-
+
/* Make assumptions about the class; we'll reset the flags if
necessary. */
CLASSTYPE_EMPTY_P (t) = 1;
= chainon (BINFO_VIRTUALS (TYPE_BINFO (t)), virtuals);
/* Set DECL_VINDEX for all functions declared in this class. */
- for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t));
- fn;
- fn = TREE_CHAIN (fn),
+ for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t));
+ fn;
+ fn = TREE_CHAIN (fn),
vindex += (TARGET_VTABLE_USES_DESCRIPTORS
? TARGET_VTABLE_USES_DESCRIPTORS : 1))
{
working on. */
for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
+ && TREE_TYPE (x) != error_mark_node
&& same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (x)), t))
DECL_MODE (x) = TYPE_MODE (t);
if (n_fields > 7)
{
struct sorted_fields_type *field_vec = GGC_NEWVAR
- (struct sorted_fields_type,
- sizeof (struct sorted_fields_type) + n_fields * sizeof (tree));
+ (struct sorted_fields_type,
+ sizeof (struct sorted_fields_type) + n_fields * sizeof (tree));
field_vec->len = n_fields;
add_fields_to_record_type (TYPE_FIELDS (t), field_vec, 0);
qsort (field_vec->elts, n_fields, sizeof (tree),
DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec;
}
+ /* Complain if one of the field types requires lower visibility. */
+ constrain_class_visibility (t);
+
/* Make the rtl for any new vtables we have created, and unmark
the base types we marked. */
finish_vtbls (t);
-
+
/* Build the VTT for T. */
build_vtt (t);
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);
if (warn_overloaded_virtual)
warn_hidden (t);
+ /* Class layout, assignment of virtual table slots, etc., is now
+ complete. Give the back end a chance to tweak the visibility of
+ the class or perform any other required target modifications. */
+ targetm.cxx.adjust_class_at_definition (t);
+
maybe_suppress_debug_info (t);
dump_class_hierarchy (t);
-
+
/* Finish debugging output for this type. */
rest_of_type_compilation (t, ! LOCAL_CLASS_P (t));
}
/* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
reverse order, so we can't just use nreverse. */
prev = NULL_TREE;
- for (x = TYPE_FIELDS (t);
- x && TREE_CODE (x) != TYPE_DECL;
+ for (x = TYPE_FIELDS (t);
+ x && TREE_CODE (x) != TYPE_DECL;
x = next)
{
next = TREE_CHAIN (x);
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:
return TREE_TYPE (instance);
}
else if (instance == current_class_ptr)
- {
- if (nonnull)
- *nonnull = 1;
-
- /* if we're in a ctor or dtor, we know our type. */
- if (DECL_LANG_SPECIFIC (current_function_decl)
- && (DECL_CONSTRUCTOR_P (current_function_decl)
- || DECL_DESTRUCTOR_P (current_function_decl)))
- {
- if (cdtorp)
- *cdtorp = 1;
- return TREE_TYPE (TREE_TYPE (instance));
- }
- }
+ {
+ if (nonnull)
+ *nonnull = 1;
+
+ /* if we're in a ctor or dtor, we know our type. */
+ if (DECL_LANG_SPECIFIC (current_function_decl)
+ && (DECL_CONSTRUCTOR_P (current_function_decl)
+ || DECL_DESTRUCTOR_P (current_function_decl)))
+ {
+ if (cdtorp)
+ *cdtorp = 1;
+ return TREE_TYPE (TREE_TYPE (instance));
+ }
+ }
else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- {
- /* Reference variables should be references to objects. */
- if (nonnull)
+ {
+ /* 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
+ 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;
{
current_class_depth = 0;
current_class_stack_size = 10;
- current_class_stack
- = xmalloc (current_class_stack_size * sizeof (struct class_stack_node));
+ current_class_stack
+ = XNEWVEC (struct class_stack_node, current_class_stack_size);
local_classes = VEC_alloc (tree, gc, 8);
+ sizeof_biggest_empty_class = size_zero_node;
ridpointers[(int) RID_PUBLIC] = access_public_node;
ridpointers[(int) RID_PRIVATE] = access_private_node;
push_binding_level (previous_class_level);
class_binding_level = previous_class_level;
/* Restore IDENTIFIER_TYPE_VALUE. */
- for (type = class_binding_level->type_shadowed;
- type;
+ for (type = class_binding_level->type_shadowed;
+ type;
type = TREE_CHAIN (type))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (type), TREE_TYPE (type));
}
void
pushclass (tree type)
{
+ class_stack_node_t csn;
+
type = TYPE_MAIN_VARIANT (type);
/* Make sure there is enough room for the new entry on the stack. */
- if (current_class_depth + 1 >= current_class_stack_size)
+ if (current_class_depth + 1 >= current_class_stack_size)
{
current_class_stack_size *= 2;
current_class_stack
- = xrealloc (current_class_stack,
- current_class_stack_size
- * sizeof (struct class_stack_node));
+ = XRESIZEVEC (struct class_stack_node, current_class_stack,
+ current_class_stack_size);
}
/* Insert a new entry on the class stack. */
- current_class_stack[current_class_depth].name = current_class_name;
- current_class_stack[current_class_depth].type = current_class_type;
- current_class_stack[current_class_depth].access = current_access_specifier;
- current_class_stack[current_class_depth].names_used = 0;
+ csn = current_class_stack + current_class_depth;
+ csn->name = current_class_name;
+ csn->type = current_class_type;
+ csn->access = current_access_specifier;
+ csn->names_used = 0;
+ csn->hidden = 0;
current_class_depth++;
/* Now set up the new type. */
/* By default, things in classes are private, while things in
structures or unions are public. */
- current_access_specifier = (CLASSTYPE_DECLARED_CLASS (type)
- ? access_private_node
+ current_access_specifier = (CLASSTYPE_DECLARED_CLASS (type)
+ ? access_private_node
: access_public_node);
if (previous_class_level
invalidate_class_lookup_cache ();
}
- if (!previous_class_level
+ if (!previous_class_level
|| type != previous_class_level->this_entity
|| current_class_depth > 1)
pushlevel_class ();
{
previous_class_level = NULL;
}
-
+
/* Get out of the current class scope. If we were in a class scope
previously, that is the one popped to. */
splay_tree_delete (current_class_stack[current_class_depth].names_used);
}
-/* Returns 1 if current_class_type is either T or a nested type of T.
- We start looking from 1 because entry 0 is from global scope, and has
- no type. */
+/* Mark the top of the class stack as hidden. */
-int
+void
+push_class_stack (void)
+{
+ if (current_class_depth)
+ ++current_class_stack[current_class_depth - 1].hidden;
+}
+
+/* Mark the top of the class stack as un-hidden. */
+
+void
+pop_class_stack (void)
+{
+ if (current_class_depth)
+ --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. */
+
+bool
currently_open_class (tree t)
{
int i;
- if (current_class_type && same_type_p (t, current_class_type))
- return 1;
- for (i = 1; i < current_class_depth; ++i)
- if (current_class_stack[i].type
- && same_type_p (current_class_stack [i].type, t))
- return 1;
- return 0;
+
+ /* We start looking from 1 because entry 0 is from global scope,
+ and has no type. */
+ for (i = current_class_depth; i > 0; --i)
+ {
+ tree c;
+ if (i == current_class_depth)
+ c = current_class_type;
+ else
+ {
+ if (current_class_stack[i].hidden)
+ break;
+ c = current_class_stack[i].type;
+ }
+ if (!c)
+ continue;
+ if (same_type_p (c, t))
+ return true;
+ }
+ return false;
}
/* If either current_class_type or one of its enclosing classes are derived
return current_class_type;
for (i = current_class_depth - 1; i > 0; --i)
- if (DERIVED_FROM_P (t, current_class_stack[i].type))
- return current_class_stack[i].type;
+ {
+ if (current_class_stack[i].hidden)
+ break;
+ if (DERIVED_FROM_P (t, current_class_stack[i].type))
+ return current_class_stack[i].type;
+ }
return NULL_TREE;
}
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)
+ if (type == NULL_TREE
+ || !CLASS_TYPE_P (type))
return;
-
- context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
- if (context && CLASS_TYPE_P (context))
- push_nested_class (context);
+ push_nested_class (DECL_CONTEXT (TYPE_MAIN_DECL (type)));
+
pushclass (type);
}
else
error ("language string %<\"%E\"%> not recognized", name);
}
-
+
/* Get out of the current language scope. */
void
/* Given an OVERLOAD and a TARGET_TYPE, return the function that
matches the TARGET_TYPE. If there is no satisfactory match, return
- error_mark_node, and issue a error & warning messages under 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. */
+ error_mark_node, and issue an error & warning messages under
+ 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. */
static tree
-resolve_address_of_overloaded_function (tree target_type,
+resolve_address_of_overloaded_function (tree target_type,
tree overload,
tsubst_flags_t flags,
bool template_only,
- tree explicit_targs)
+ tree explicit_targs,
+ tree access_path)
{
/* Here's what the standard says:
-
+
[over.over]
If the name is a function template, template argument deduction
|| TREE_CODE (TREE_TYPE (target_type)) != METHOD_TYPE);
gcc_assert (is_overloaded_fn (overload));
-
+
/* Check that the TARGET_TYPE is reasonable. */
if (TYPE_PTRFN_P (target_type))
/* This is OK. */;
target_type = build_reference_type (target_type);
is_reference = 1;
}
- else
+ else
{
if (flags & tf_error)
error ("cannot resolve overloaded function %qD based on"
- " conversion to type %qT",
- DECL_NAME (OVL_FUNCTION (overload)), target_type);
+ " conversion to type %qT",
+ DECL_NAME (OVL_FUNCTION (overload)), target_type);
return error_mark_node;
}
-
+
/* If we can find a non-template function that matches, we can just
use it. There's no point in generating template instantiations
if we're just going to throw them out anyhow. But, of course, we
one, or vice versa. */
continue;
- /* Ignore anticipated decls of undeclared builtins. */
+ /* Ignore functions which haven't been explicitly
+ declared. */
if (DECL_ANTICIPATED (fn))
continue;
else if (!is_reference)
fntype = build_pointer_type (fntype);
- if (can_convert_arg (target_type, fntype, fn))
+ if (can_convert_arg (target_type, fntype, fn, LOOKUP_NORMAL))
matches = tree_cons (fn, NULL_TREE, matches);
}
}
/* Now, if we've already got a match (or matches), there's no need
to proceed to the template functions. But, if we don't have a
match we need to look at them, too. */
- if (!matches)
+ if (!matches)
{
tree target_fn_type;
tree target_arg_types;
/* Never do unification on the 'this' parameter. */
if (TREE_CODE (target_fn_type) == METHOD_TYPE)
target_arg_types = TREE_CHAIN (target_arg_types);
-
+
for (fns = overload; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
targs = make_tree_vec (DECL_NTPARMS (fn));
if (fn_type_unification (fn, explicit_targs, targs,
target_arg_types, target_ret_type,
- DEDUCE_EXACT))
+ DEDUCE_EXACT, LOOKUP_NORMAL))
/* Argument deduction failed. */
continue;
/* See if there's a match. */
instantiation_type = TREE_TYPE (instantiation);
if (is_ptrmem)
- instantiation_type =
+ instantiation_type =
build_ptrmemfunc_type (build_pointer_type (instantiation_type));
else if (!is_reference)
instantiation_type = build_pointer_type (instantiation_type);
- if (can_convert_arg (target_type, instantiation_type, instantiation))
+ if (can_convert_arg (target_type, instantiation_type, instantiation,
+ LOOKUP_NORMAL))
matches = tree_cons (instantiation, fn, matches);
}
tree match = most_specialized_instantiation (matches);
if (match != error_mark_node)
- matches = tree_cons (match, NULL_TREE, NULL_TREE);
+ matches = tree_cons (TREE_PURPOSE (match),
+ NULL_TREE,
+ NULL_TREE);
}
}
/* There were *no* matches. */
if (flags & tf_error)
{
- error ("no matches converting function %qD to type %q#T",
- DECL_NAME (OVL_FUNCTION (overload)),
- target_type);
+ error ("no matches converting function %qD to type %q#T",
+ DECL_NAME (OVL_FUNCTION (overload)),
+ target_type);
/* print_candidates expects a chain with the functions in
- TREE_VALUE slots, so we cons one up here (we're losing anyway,
- so why be clever?). */
- for (; overload; overload = OVL_NEXT (overload))
- matches = tree_cons (NULL_TREE, OVL_CURRENT (overload),
+ TREE_VALUE slots, so we cons one up here (we're losing anyway,
+ so why be clever?). */
+ for (; overload; overload = OVL_NEXT (overload))
+ matches = tree_cons (NULL_TREE, OVL_CURRENT (overload),
matches);
-
+
print_candidates (matches);
}
return error_mark_node;
{
tree match;
- error ("converting overloaded function %qD to type %q#T is ambiguous",
+ error ("converting overloaded function %qD to type %q#T is ambiguous",
DECL_NAME (OVL_FUNCTION (overload)),
target_type);
print_candidates (matches);
}
-
+
return error_mark_node;
}
&& !(flags & tf_ptrmem_ok) && !flag_ms_extensions)
{
static int explained;
-
+
if (!(flags & tf_error))
- return error_mark_node;
+ return error_mark_node;
pedwarn ("assuming pointer to member %qD", fn);
if (!explained)
- {
- pedwarn ("(a pointer to member can only be formed with %<&%E%>)", fn);
- explained = 1;
- }
+ {
+ pedwarn ("(a pointer to member can only be formed with %<&%E%>)", fn);
+ explained = 1;
+ }
}
/* If we're doing overload resolution purely for the purpose of
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);
+ {
+ 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);
+ }
+ }
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
return build_unary_op (ADDR_EXPR, fn, 0);
we complain on errors. If we are not complaining, never modify rhs,
as overload resolution wants to try many possible instantiations, in
the hope that at least one will work.
-
+
For non-recursive calls, LHSTYPE should be a function, pointer to
function, or a pointer to member function. */
instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
{
tsubst_flags_t flags_in = flags;
-
+ tree access_path = NULL_TREE;
+
flags &= ~tf_ptrmem_ok;
-
+
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
if (flags & tf_error)
{
if (same_type_p (lhstype, TREE_TYPE (rhs)))
return rhs;
- if (flag_ms_extensions
+ if (flag_ms_extensions
&& TYPE_PTRMEMFUNC_P (lhstype)
&& !TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
/* Microsoft allows `A::f' to be resolved to a
}
if (TREE_CODE (rhs) == BASELINK)
- rhs = BASELINK_FUNCTIONS (rhs);
+ {
+ access_path = BASELINK_ACCESS_BINFO (rhs);
+ rhs = BASELINK_FUNCTIONS (rhs);
+ }
/* If we are in a template, and have a NON_DEPENDENT_EXPR, we cannot
deduce any type information. */
return error_mark_node;
}
+ /* There only a few kinds of expressions that may have a type
+ 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)
switch (TREE_CODE (rhs))
{
- case TYPE_EXPR:
- case CONVERT_EXPR:
- case SAVE_EXPR:
- case CONSTRUCTOR:
- gcc_unreachable ();
-
- case INDIRECT_REF:
- case ARRAY_REF:
- {
- tree new_rhs;
-
- new_rhs = instantiate_type (build_pointer_type (lhstype),
- TREE_OPERAND (rhs, 0), flags);
- if (new_rhs == error_mark_node)
- return error_mark_node;
-
- TREE_TYPE (rhs) = lhstype;
- TREE_OPERAND (rhs, 0) = new_rhs;
- return rhs;
- }
-
- case NOP_EXPR:
- rhs = copy_node (TREE_OPERAND (rhs, 0));
- TREE_TYPE (rhs) = unknown_type_node;
- return instantiate_type (lhstype, rhs, flags);
-
case COMPONENT_REF:
{
tree member = TREE_OPERAND (rhs, 1);
case OFFSET_REF:
rhs = TREE_OPERAND (rhs, 1);
if (BASELINK_P (rhs))
- return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags_in);
+ return instantiate_type (lhstype, rhs, flags_in);
/* This can happen if we are forming a pointer-to-member for a
member template. */
return
resolve_address_of_overloaded_function (lhstype, fns, flags_in,
/*template_only=*/true,
- args);
+ args, access_path);
}
case OVERLOAD:
case FUNCTION_DECL:
- return
+ return
resolve_address_of_overloaded_function (lhstype, rhs, flags_in,
/*template_only=*/false,
- /*explicit_targs=*/NULL_TREE);
+ /*explicit_targs=*/NULL_TREE,
+ access_path);
- case CALL_EXPR:
- /* This is too hard for now. */
- gcc_unreachable ();
-
- case PLUS_EXPR:
- case MINUS_EXPR:
case COMPOUND_EXPR:
TREE_OPERAND (rhs, 0)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
TREE_TYPE (rhs) = lhstype;
return rhs;
- case MULT_EXPR:
- case TRUNC_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case RDIV_EXPR:
- case TRUNC_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case CEIL_MOD_EXPR:
- case ROUND_MOD_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_CEIL_EXPR:
- case FIX_TRUNC_EXPR:
- case FLOAT_EXPR:
- case NEGATE_EXPR:
- case ABS_EXPR:
- case MAX_EXPR:
- case MIN_EXPR:
-
- case BIT_AND_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case LROTATE_EXPR:
- case RROTATE_EXPR:
-
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- if (flags & tf_error)
- error ("invalid operation on uninstantiated type");
- return error_mark_node;
-
- case TRUTH_AND_EXPR:
- case TRUTH_OR_EXPR:
- case TRUTH_XOR_EXPR:
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- case TRUTH_ANDIF_EXPR:
- case TRUTH_ORIF_EXPR:
- case TRUTH_NOT_EXPR:
- if (flags & tf_error)
- error ("not enough type information");
- return error_mark_node;
-
- case COND_EXPR:
- if (type_unknown_p (TREE_OPERAND (rhs, 0)))
- {
- if (flags & tf_error)
- error ("not enough type information");
- 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_OPERAND (rhs, 2)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), flags);
- if (TREE_OPERAND (rhs, 2) == error_mark_node)
- return error_mark_node;
-
- TREE_TYPE (rhs) = lhstype;
- return rhs;
-
- case MODIFY_EXPR:
- 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))
- flags |= tf_ptrmem_ok;
-
+ flags |= tf_ptrmem_ok;
+
return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
}
|| !TYPE_CONTAINS_VPTR_P (BINFO_TYPE (base_binfo)))
break;
}
-
+
type = BINFO_TYPE (binfo);
- buf = alloca (sizeof (VFIELD_NAME_FORMAT) + TYPE_NAME_LENGTH (type) + 2);
+ buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT)
+ + TYPE_NAME_LENGTH (type) + 2);
sprintf (buf, VFIELD_NAME_FORMAT,
IDENTIFIER_POINTER (constructor_name (type)));
return get_identifier (buf);
/* Build a dummy reference to ourselves so Derived::Base (and A::A) works,
according to [class]:
- The class-name is also inserted
+ The class-name is also inserted
into the scope of the class itself. For purposes of access checking,
the inserted class name is treated as if it were a public member name. */
if (!(innermost_scope_kind() == sk_class
&& TYPE_BEING_DEFINED (current_class_type)))
return;
-
+
/* If there's already a binding for this NAME, then we don't have
anything to worry about. */
- if (lookup_member (current_class_type, name,
+ if (lookup_member (current_class_type, name,
/*protect=*/0, /*want_type=*/false))
return;
names_used = current_class_stack[current_class_depth - 1].names_used;
splay_tree_insert (names_used,
- (splay_tree_key) name,
+ (splay_tree_key) name,
(splay_tree_value) decl);
}
splay_tree_node n;
/* Look to see if we ever used this name. */
- names_used
+ names_used
= current_class_stack[current_class_depth - 1].names_used;
if (!names_used)
return;
if (n)
{
/* [basic.scope.class]
-
+
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);
- cp_error_at ("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);
BINFO in the complete object. Check BINFO_PRIMARY_P or
BINFO_LOST_PRIMARY_P to be sure. */
-tree
+static tree
get_primary_binfo (tree binfo)
{
tree primary_base;
- tree result;
-
+
primary_base = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo));
if (!primary_base)
return NULL_TREE;
- result = copied_binfo (primary_base, binfo);
- return result;
+ return copied_binfo (primary_base, binfo);
}
/* If INDENTED_P is zero, indent to INDENT. Return nonzero. */
static tree
dump_class_hierarchy_r (FILE *stream,
- int flags,
- tree binfo,
- tree igo,
- int indent)
+ int flags,
+ tree binfo,
+ tree igo,
+ int indent)
{
int indented = 0;
tree base_binfo;
int i;
-
+
indented = maybe_indent_hierarchy (stream, indent, 0);
fprintf (stream, "%s (0x%lx) ",
type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER),
return igo;
}
igo = TREE_CHAIN (binfo);
-
+
fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (BINFO_OFFSET (binfo), 0));
if (is_empty_class (BINFO_TYPE (binfo)))
if (!(flags & TDF_SLIM))
{
int indented = 0;
-
+
if (BINFO_SUBVTT_INDEX (binfo))
{
indented = maybe_indent_hierarchy (stream, indent + 3, indented);
expr_as_string (BINFO_VTABLE (binfo),
TFF_PLAIN_IDENTIFIER));
}
-
+
if (indented)
fprintf (stream, "\n");
}
for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
igo = dump_class_hierarchy_r (stream, flags, base_binfo, igo, indent + 2);
-
+
return igo;
}
/* Debug interface to hierarchy dumping. */
-extern void
+void
debug_class (tree t)
{
dump_class_hierarchy_1 (stderr, TDF_SLIM, t);
static void
dump_array (FILE * stream, tree decl)
{
- tree inits;
- int ix;
+ tree value;
+ unsigned HOST_WIDE_INT ix;
HOST_WIDE_INT elt;
tree size = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (decl)));
TFF_PLAIN_IDENTIFIER));
fprintf (stream, "\n");
- for (ix = 0, inits = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
- inits; ix++, inits = TREE_CHAIN (inits))
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)),
+ ix, value)
fprintf (stream, "%-4ld %s\n", (long)(ix * elt),
- expr_as_string (TREE_VALUE (inits), TFF_PLAIN_IDENTIFIER));
+ expr_as_string (value, TFF_PLAIN_IDENTIFIER));
}
static void
if (!(flags & TDF_SLIM))
{
int ctor_vtbl_p = TYPE_BINFO (t) != binfo;
-
+
fprintf (stream, "%s for %s",
ctor_vtbl_p ? "Construction vtable" : "Vtable",
type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER));
dump_array (stream, vtable);
fprintf (stream, "\n");
}
-
+
dump_end (TDI_class, stream);
}
dump_array (stream, vtt);
fprintf (stream, "\n");
}
-
+
dump_end (TDI_class, stream);
}
static const char spaces[] = " ";
tree name = DECL_NAME (thunk);
tree thunks;
-
+
fprintf (stream, "%.*s%p %s %s", indent, spaces,
(void *)thunk,
!DECL_THUNK_P (thunk) ? "function"
/* Dump the thunks for FN. */
-extern void
+void
debug_thunks (tree fn)
{
dump_thunk (stderr, 0, fn);
list = build_tree_list (BINFO_VTABLE (TYPE_BINFO (t)), NULL_TREE);
accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t),
TYPE_BINFO (t), t, list);
-
+
/* Then come the virtual bases, also in inheritance graph order. */
for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
{
/* Build the VTT (virtual table table) for T.
A class requires a VTT if it has virtual bases.
-
+
This holds
1 - primary virtual pointer for complete object T
2 - secondary VTTs for each direct non-virtual base of T which requires a
3 - secondary virtual pointers for each direct or indirect base of T which
has virtual bases or is reachable via a virtual path from T.
4 - secondary VTTs for each direct or indirect virtual base of T.
-
+
Secondary VTTs look like complete object VTTs without part 4. */
static void
/* Figure out the type of the VTT. */
type = build_index_type (size_int (list_length (inits) - 1));
type = build_cplus_array_type (const_ptr_type_node, type);
-
+
/* Now, build the VTT object itself. */
- vtt = build_vtable (t, get_vtt_name (t), type);
+ vtt = build_vtable (t, mangle_vtt_for_type (t), type);
initialize_artificial_var (vtt, inits);
/* Add the VTT to the vtables list. */
TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));
BINFO_VPTR_INDEX (binfo) = *index;
}
*index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
-
+
/* Recursively add the secondary VTTs for non-virtual bases. */
for (i = 0; BINFO_BASE_ITERATE (binfo, i, b); ++i)
if (!BINFO_VIRTUAL_P (b))
inits = build_vtt_inits (b, t, inits, index);
-
+
/* Add secondary virtual pointers for all subobjects of BINFO with
either virtual bases or reachable along a virtual path, except
subobjects that are non-virtual primary bases. */
data.index = *index;
data.inits = NULL;
data.type_being_constructed = BINFO_TYPE (binfo);
-
+
dfs_walk_once (binfo, dfs_build_secondary_vptr_vtt_inits, NULL, &data);
*index = data.index;
{
if (!BINFO_VIRTUAL_P (b))
continue;
-
+
inits = build_vtt_inits (b, t, inits, index);
}
else
if (!(CLASSTYPE_VBASECLASSES (BINFO_TYPE (binfo))
|| binfo_via_virtual (binfo, data->type_being_constructed)))
return dfs_skip_bases;
-
+
/* We're not interested in non-virtual primary bases. */
if (!BINFO_VIRTUAL_P (binfo) && BINFO_PRIMARY_P (binfo))
return NULL_TREE;
-
+
/* Record the index where this secondary vptr can be found. */
if (data->top_level_p)
{
if (BINFO_VIRTUAL_P (binfo))
{
- /* It's a primary virtual base, and this is not a
- construction vtable. Find the base this is primary of in
- the inheritance graph, and use that base's vtable
- now. */
+ /* It's a primary virtual base, and this is not a
+ construction vtable. Find the base this is primary of in
+ the inheritance graph, and use that base's vtable
+ now. */
while (BINFO_PRIMARY_P (binfo))
binfo = BINFO_INHERITANCE_CHAIN (binfo);
}
}
-
+
/* Add the initializer for the secondary vptr itself. */
data->inits = tree_cons (NULL_TREE, binfo_ctor_vtable (binfo), data->inits);
if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
/* If this class has no vtable, none of its bases do. */
return dfs_skip_bases;
-
+
if (!vtable)
/* This might be a primary base, so have no vtable in this
hierarchy. */
return NULL_TREE;
-
+
/* If we scribbled the construction vtable vptr into BINFO, clear it
out now. */
if (TREE_CODE (vtable) == TREE_LIST
/* Add the vtables for each of our virtual bases using the vbase in T
binfo. */
- for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
- vbase;
+ for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
+ vbase;
vbase = TREE_CHAIN (vbase))
{
tree b;
if (!BINFO_VIRTUAL_P (vbase))
continue;
b = copied_binfo (vbase, binfo);
-
+
accumulate_vtbl_inits (b, vbase, binfo, t, list);
}
inits = TREE_VALUE (list);
/* 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);
static void
accumulate_vtbl_inits (tree binfo,
- tree orig_binfo,
- tree rtti_binfo,
- tree t,
- tree inits)
+ tree orig_binfo,
+ tree rtti_binfo,
+ tree t,
+ tree inits)
{
int i;
tree base_binfo;
/* If it doesn't have a vptr, we don't do anything. */
if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
return;
-
+
/* If we're building a construction vtable, we're not interested in
subobjects that don't require construction vtables. */
- if (ctor_vtbl_p
+ if (ctor_vtbl_p
&& !CLASSTYPE_VBASECLASSES (BINFO_TYPE (binfo))
&& !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo)))
return;
/* Build the initializers for the BINFO-in-T vtable. */
- TREE_VALUE (inits)
+ TREE_VALUE (inits)
= chainon (TREE_VALUE (inits),
dfs_accumulate_vtbl_inits (binfo, orig_binfo,
rtti_binfo, t, inits));
-
+
/* Walk the BINFO and its bases. We walk in preorder so that as we
initialize each vtable we can figure out at what offset the
secondary vtable lies from the primary vtable. We can't use
static tree
dfs_accumulate_vtbl_inits (tree binfo,
- tree orig_binfo,
- tree rtti_binfo,
- tree t,
- tree l)
+ tree orig_binfo,
+ tree rtti_binfo,
+ tree t,
+ tree l)
{
tree inits = NULL_TREE;
tree vtbl = NULL_TREE;
primary, we still need a VTT entry for the vtable, but it
should point to the ctor vtable for the base it is a
primary for within the sub-hierarchy of RTTI_BINFO.
-
+
There are three possible cases:
-
+
1) We are in the same place.
2) We are a primary base within a lost primary virtual base of
RTTI_BINFO.
3) We are primary to something not a base of RTTI_BINFO. */
-
+
tree b;
tree last = NULL_TREE;
if (BINFO_VIRTUAL_P (b) || b == rtti_binfo)
break;
found:
-
+
/* If we found RTTI_BINFO, this is case 1. If we found a virtual
base B and it is a base of RTTI_BINFO, this is case 2. In
either case, we share our vtable with LAST, i.e. the
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)
The value returned is a TREE_LIST suitable for wrapping in a
CONSTRUCTOR to use as the DECL_INITIAL for a vtable. If
NON_FN_ENTRIES_P is not NULL, *NON_FN_ENTRIES_P is set to the
- number of non-function entries in the vtable.
+ number of non-function entries in the vtable.
It might seem that this function should never be called with a
BINFO for which BINFO_PRIMARY_P holds, the vtable for such a
static tree
build_vtbl_initializer (tree binfo,
- tree orig_binfo,
- tree t,
- tree rtti_binfo,
- int* non_fn_entries_p)
+ tree orig_binfo,
+ tree t,
+ tree rtti_binfo,
+ int* non_fn_entries_p)
{
tree v, b;
tree vfun_inits;
unsigned ix;
tree vbinfo;
VEC(tree,gc) *vbases;
-
+
/* Initialize VID. */
memset (&vid, 0, sizeof (vid));
vid.binfo = binfo;
vid.fns = VEC_alloc (tree, gc, 32);
/* Add the vcall and vbase offset entries. */
build_vcall_and_vbase_vtbl_entries (binfo, &vid);
-
+
/* Clear BINFO_VTABLE_PATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
for (vbases = CLASSTYPE_VBASECLASSES (t), ix = 0;
tree vcall_index;
tree fn, fn_original;
tree init = NULL_TREE;
-
+
fn = BV_FN (v);
fn_original = fn;
if (DECL_THUNK_P (fn))
}
fn_original = THUNK_TARGET (fn);
}
-
+
/* If the only definition of this function signature along our
primary base chain is from a lost primary, this vtable slot will
never be used, so just zero it out. This is important to avoid
}
}
else
- vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
+ vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
}
/* The initializers for virtual functions were built up in reverse
order; straighten them out now. */
vfun_inits = nreverse (vfun_inits);
-
+
/* The negative offset initializers are also in reverse order. */
vid.inits = nreverse (vid.inits);
return;
t = vid->derived;
-
+
/* We might be a primary base class. Go up the inheritance hierarchy
until we find the most derived class of which we are a primary base:
it is the offset of that which we need to use. */
{
tree b;
tree delta;
-
+
if (!BINFO_VIRTUAL_P (vbase))
continue;
BINFO_VTABLE_PATH_MARKED (b) = 1;
/* Figure out where we can find this vbase offset. */
- delta = size_binop (MULT_EXPR,
+ delta = size_binop (MULT_EXPR,
vid->index,
convert (ssizetype,
TYPE_SIZE_UNIT (vtable_entry_type)));
we are walking in inheritance graph order so these end up in
the right order. */
delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (non_primary_binfo));
-
- *vid->last_init
+
+ *vid->last_init
= build_tree_list (NULL_TREE,
- fold_build1 (NOP_EXPR,
+ fold_build1 (NOP_EXPR,
vtable_entry_type,
delta));
vid->last_init = &TREE_CHAIN (*vid->last_init);
/* We only need these entries if this base is a virtual base. We
compute the indices -- but do not add to the vtable -- when
building the main vtable for a class. */
- if (BINFO_VIRTUAL_P (binfo) || binfo == TYPE_BINFO (vid->derived))
+ if (binfo == TYPE_BINFO (vid->derived)
+ || (BINFO_VIRTUAL_P (binfo)
+ /* If BINFO is RTTI_BINFO, then (since BINFO does not
+ correspond to VID->DERIVED), we are building a primary
+ construction virtual table. Since this is a primary
+ virtual table, we do not need the vcall offsets for
+ BINFO. */
+ && binfo != vid->rtti_binfo))
{
/* We need a vcall offset for each of the virtual functions in this
vtable. For example:
through the recursion in build_vcall_and_vbase_vtbl_entries. */
if (BINFO_VIRTUAL_P (binfo) && vid->vbase != binfo)
return;
-
+
/* If BINFO has a primary base, process it first. */
primary_binfo = get_primary_binfo (binfo);
if (primary_binfo)
where rtti_binfo is the most derived type. */
non_primary_binfo
= original_binfo (non_primary_binfo, vid->rtti_binfo);
-
+
for (base_virtuals = BINFO_VIRTUALS (binfo),
derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
orig_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
signature as FN, then we do not need a second vcall offset.
Check the list of functions already present in the derived
class vtable. */
- for (i = 0; VEC_iterate (tree, vid->fns, i, derived_entry); ++i)
+ for (i = 0; VEC_iterate (tree, vid->fns, i, derived_entry); ++i)
{
if (same_signature_p (derived_entry, orig_fn)
/* We only use one vcall offset for virtual destructors,
elt->purpose = orig_fn;
elt->value = vid->index;
}
-
+
/* The next vcall offset will be found at a more negative
offset. */
vid->index = size_binop (MINUS_EXPR, vid->index,
primary base, and then add the offset in the vtbl to that value. */
b = binfo;
while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b))
- && !BINFO_LOST_PRIMARY_P (b))
+ && !BINFO_LOST_PRIMARY_P (b))
{
tree primary_base;
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 = build_nop (vfunc_ptr_type_node, decl);