/* Functions related to building classes and their related objects.
- Copyright (C) 1987-2013 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "options.h"
+#include "wide-int.h"
+#include "inchash.h"
#include "tm.h"
#include "tree.h"
#include "stringpool.h"
#include "stor-layout.h"
#include "attribs.h"
-#include "gimple.h"
+#include "hash-table.h"
#include "cp-tree.h"
#include "flags.h"
#include "toplev.h"
#include "target.h"
#include "convert.h"
+#include "hash-map.h"
+#include "is-a.h"
+#include "plugin-api.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "ipa-ref.h"
#include "cgraph.h"
#include "dumpfile.h"
#include "splay-tree.h"
-#include "pointer-set.h"
-#include "hash-table.h"
-#include "gimple.h"
#include "gimplify.h"
+#include "wide-int.h"
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
static tree get_vfield_name (tree);
static void finish_struct_anon (tree);
static tree get_vtable_name (tree);
-static tree get_basefndecls (tree, tree);
+static void get_basefndecls (tree, tree, vec<tree> *);
static int build_primary_vtable (tree, tree);
static int build_secondary_vtable (tree);
static void finish_vtbls (tree);
static void build_base_fields (record_layout_info, splay_tree, tree *);
static void check_methods (tree);
static void remove_zero_width_bit_fields (tree);
+static bool accessible_nvdtor_p (tree);
static void check_bases (tree, int *, int *);
static void check_bases_and_members (tree);
static tree create_vtable_ptr (tree, tree *);
splay_tree_key k2);
static void warn_about_ambiguous_bases (tree);
static bool type_requires_array_cookie (tree);
-static bool contains_empty_class_p (tree);
static bool base_derived_from (tree, tree);
static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
static tree end_of_base (tree);
int want_pointer = TYPE_PTR_P (TREE_TYPE (expr));
bool has_empty = false;
bool virtual_access;
+ bool rvalue = false;
if (expr == error_mark_node || binfo == error_mark_node || !binfo)
return error_mark_node;
}
if (!want_pointer)
- /* This must happen before the call to save_expr. */
- expr = cp_build_addr_expr (expr, complain);
+ {
+ rvalue = !real_lvalue_p (expr);
+ /* This must happen before the call to save_expr. */
+ expr = cp_build_addr_expr (expr, complain);
+ }
else
expr = mark_rvalue_use (expr);
/* Don't bother with the calculations inside sizeof; they'll ICE if the
source type is incomplete and the pointer value doesn't matter. In a
- template (even in fold_non_dependent_expr), we don't have vtables set
- up properly yet, and the value doesn't matter there either; we're just
- interested in the result of overload resolution. */
+ template (even in instantiate_non_dependent_expr), we don't have vtables
+ set up properly yet, and the value doesn't matter there either; we're
+ just interested in the result of overload resolution. */
if (cp_unevaluated_operand != 0
|| in_template_function ())
{
expr = build_nop (ptr_target_type, expr);
- if (!want_pointer)
- expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
- return expr;
+ goto indout;
}
/* If we're in an NSDMI, we don't have the full constructor context yet
{
expr = build1 (CONVERT_EXPR, ptr_target_type, expr);
CONVERT_EXPR_VBASE_PATH (expr) = true;
- if (!want_pointer)
- expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
- return expr;
+ goto indout;
}
/* Do we need to check for a null pointer? */
{
expr = cp_build_indirect_ref (expr, RO_NULL, complain);
expr = build_simple_base_path (expr, binfo);
+ if (rvalue)
+ expr = move (expr);
if (want_pointer)
expr = build_address (expr);
target_type = TREE_TYPE (expr);
v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
}
else
- v_offset = build_vfield_ref (cp_build_indirect_ref (expr, RO_NULL,
- complain),
- TREE_TYPE (TREE_TYPE (expr)));
+ {
+ tree t = expr;
+ if ((flag_sanitize & SANITIZE_VPTR) && fixed_type_p == 0)
+ {
+ t = cp_ubsan_maybe_instrument_cast_to_vbase (input_location,
+ probe, expr);
+ if (t == NULL_TREE)
+ t = expr;
+ }
+ v_offset = build_vfield_ref (cp_build_indirect_ref (t, RO_NULL,
+ complain),
+ TREE_TYPE (TREE_TYPE (expr)));
+ }
+
+ if (v_offset == error_mark_node)
+ return error_mark_node;
v_offset = fold_build_pointer_plus (v_offset, BINFO_VPTR_FIELD (v_binfo));
v_offset = build1 (NOP_EXPR,
else
null_test = NULL;
+ indout:
if (!want_pointer)
- expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+ {
+ expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+ if (rvalue)
+ expr = move (expr);
+ }
out:
if (null_test)
{
tree vfield, vcontext;
- if (datum == error_mark_node)
+ if (datum == error_mark_node
+ /* Can happen in case of duplicate base types (c++/59082). */
+ || !TYPE_VFIELD (type))
return error_mark_node;
/* First, convert to the requested type. */
TREE_READONLY (decl) = 1;
DECL_VIRTUAL_P (decl) = 1;
DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN;
+ DECL_USER_ALIGN (decl) = true;
DECL_VTABLE_OR_VTT_P (decl) = 1;
- /* At one time the vtable info was grabbed 2 words at a time. This
- fails on sparc unless you have 8-byte alignment. (tiemann) */
- DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
- DECL_ALIGN (decl));
set_linkage_according_to_type (class_type, decl);
/* The vtable has not been defined -- yet. */
DECL_EXTERNAL (decl) = 1;
if (DECL_ASSEMBLER_NAME_SET_P (method))
mangle_decl (method);
}
- record_function_versions (fn, method);
+ cgraph_node::record_function_versions (fn, method);
continue;
}
if (DECL_INHERITED_CTOR_BASE (method))
old_value = NULL_TREE;
}
- cp_emit_debug_info_for_using (decl, USING_DECL_SCOPE (using_decl));
+ cp_emit_debug_info_for_using (decl, t);
if (is_overloaded_fn (decl))
flist = decl;
alter_access (t, decl, access);
}
\f
-/* walk_tree callback for check_abi_tags: if the type at *TP involves any
- types with abi tags, add the corresponding identifiers to the VEC in
- *DATA and set IDENTIFIER_MARKED. */
+/* Data structure for find_abi_tags_r, below. */
struct abi_tag_data
{
- tree t;
- tree subob;
+ tree t; // The type that we're checking for missing tags.
+ tree subob; // The subobject of T that we're getting tags from.
+ tree tags; // error_mark_node for diagnostics, or a list of missing tags.
};
-static tree
-find_abi_tags_r (tree *tp, int */*walk_subtrees*/, void *data)
-{
- if (!OVERLOAD_TYPE_P (*tp))
- return NULL_TREE;
+/* Subroutine of find_abi_tags_r. Handle a single TAG found on the class TP
+ in the context of P. TAG can be either an identifier (the DECL_NAME of
+ a tag NAMESPACE_DECL) or a STRING_CST (a tag attribute). */
- if (tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (*tp)))
+static void
+check_tag (tree tag, tree id, tree *tp, abi_tag_data *p)
+{
+ if (!IDENTIFIER_MARKED (id))
{
- struct abi_tag_data *p = static_cast<struct abi_tag_data*>(data);
- for (tree list = TREE_VALUE (attributes); list;
- list = TREE_CHAIN (list))
+ if (p->tags != error_mark_node)
{
- tree tag = TREE_VALUE (list);
- tree id = get_identifier (TREE_STRING_POINTER (tag));
- if (!IDENTIFIER_MARKED (id))
+ /* We're collecting tags from template arguments or from
+ the type of a variable or function return type. */
+ p->tags = tree_cons (NULL_TREE, tag, p->tags);
+
+ /* Don't inherit this tag multiple times. */
+ IDENTIFIER_MARKED (id) = true;
+
+ if (TYPE_P (p->t))
{
- if (TYPE_P (p->subob))
- {
- warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
- "that base %qT has", p->t, tag, p->subob);
- inform (location_of (p->subob), "%qT declared here",
- p->subob);
- }
- else
- {
- warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
- "that %qT (used in the type of %qD) has",
- p->t, tag, *tp, p->subob);
- inform (location_of (p->subob), "%qD declared here",
- p->subob);
- inform (location_of (*tp), "%qT declared here", *tp);
- }
+ /* Tags inherited from type template arguments are only used
+ to avoid warnings. */
+ ABI_TAG_IMPLICIT (p->tags) = true;
+ return;
+ }
+ /* For functions and variables we want to warn, too. */
+ }
+
+ /* Otherwise we're diagnosing missing tags. */
+ if (TREE_CODE (p->t) == FUNCTION_DECL)
+ {
+ if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag "
+ "that %qT (used in its return type) has",
+ p->t, tag, *tp))
+ inform (location_of (*tp), "%qT declared here", *tp);
+ }
+ else if (TREE_CODE (p->t) == VAR_DECL)
+ {
+ if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag "
+ "that %qT (used in its type) has", p->t, tag, *tp))
+ inform (location_of (*tp), "%qT declared here", *tp);
+ }
+ else if (TYPE_P (p->subob))
+ {
+ if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag "
+ "that base %qT has", p->t, tag, p->subob))
+ inform (location_of (p->subob), "%qT declared here",
+ p->subob);
+ }
+ else
+ {
+ if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag "
+ "that %qT (used in the type of %qD) has",
+ p->t, tag, *tp, p->subob))
+ {
+ inform (location_of (p->subob), "%qD declared here",
+ p->subob);
+ inform (location_of (*tp), "%qT declared here", *tp);
}
}
}
- return NULL_TREE;
}
-/* Set IDENTIFIER_MARKED on all the ABI tags on T and its (transitively
- complete) template arguments. */
+/* Find all the ABI tags in the attribute list ATTR and either call
+ check_tag (if TP is non-null) or set IDENTIFIER_MARKED to val. */
+
+static void
+mark_or_check_attr_tags (tree attr, tree *tp, abi_tag_data *p, bool val)
+{
+ if (!attr)
+ return;
+ for (; (attr = lookup_attribute ("abi_tag", attr));
+ attr = TREE_CHAIN (attr))
+ for (tree list = TREE_VALUE (attr); list;
+ list = TREE_CHAIN (list))
+ {
+ tree tag = TREE_VALUE (list);
+ tree id = get_identifier (TREE_STRING_POINTER (tag));
+ if (tp)
+ check_tag (tag, id, tp, p);
+ else
+ IDENTIFIER_MARKED (id) = val;
+ }
+}
+
+/* Find all the ABI tags on T and its enclosing scopes and either call
+ check_tag (if TP is non-null) or set IDENTIFIER_MARKED to val. */
static void
-mark_type_abi_tags (tree t, bool val)
+mark_or_check_tags (tree t, tree *tp, abi_tag_data *p, bool val)
{
- tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t));
- if (attributes)
+ while (t != global_namespace)
{
- for (tree list = TREE_VALUE (attributes); list;
- list = TREE_CHAIN (list))
+ tree attr;
+ if (TYPE_P (t))
{
- tree tag = TREE_VALUE (list);
- tree id = get_identifier (TREE_STRING_POINTER (tag));
- IDENTIFIER_MARKED (id) = val;
+ attr = TYPE_ATTRIBUTES (t);
+ t = CP_TYPE_CONTEXT (t);
}
+ else
+ {
+ attr = DECL_ATTRIBUTES (t);
+ t = CP_DECL_CONTEXT (t);
+ }
+ mark_or_check_attr_tags (attr, tp, p, val);
}
+}
- /* Also mark ABI tags from template arguments. */
- if (CLASSTYPE_TEMPLATE_INFO (t))
+/* walk_tree callback for check_abi_tags: if the type at *TP involves any
+ types with ABI tags, add the corresponding identifiers to the VEC in
+ *DATA and set IDENTIFIER_MARKED. */
+
+static tree
+find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (!OVERLOAD_TYPE_P (*tp))
+ return NULL_TREE;
+
+ /* walk_tree shouldn't be walking into any subtrees of a RECORD_TYPE
+ anyway, but let's make sure of it. */
+ *walk_subtrees = false;
+
+ abi_tag_data *p = static_cast<struct abi_tag_data*>(data);
+
+ mark_or_check_tags (*tp, tp, p, false);
+
+ return NULL_TREE;
+}
+
+/* walk_tree callback for mark_abi_tags: if *TP is a class, set
+ IDENTIFIER_MARKED on its ABI tags. */
+
+static tree
+mark_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (!OVERLOAD_TYPE_P (*tp))
+ return NULL_TREE;
+
+ /* walk_tree shouldn't be walking into any subtrees of a RECORD_TYPE
+ anyway, but let's make sure of it. */
+ *walk_subtrees = false;
+
+ bool *valp = static_cast<bool*>(data);
+
+ mark_or_check_tags (*tp, NULL, NULL, *valp);
+
+ return NULL_TREE;
+}
+
+/* Set IDENTIFIER_MARKED on all the ABI tags on T and its enclosing
+ scopes. */
+
+static void
+mark_abi_tags (tree t, bool val)
+{
+ mark_or_check_tags (t, NULL, NULL, val);
+ if (DECL_P (t))
{
- tree args = CLASSTYPE_TI_ARGS (t);
- for (int i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
+ if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
{
- tree level = TMPL_ARGS_LEVEL (args, i+1);
+ /* Template arguments are part of the signature. */
+ tree level = INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (t));
for (int j = 0; j < TREE_VEC_LENGTH (level); ++j)
{
tree arg = TREE_VEC_ELT (level, j);
- if (CLASS_TYPE_P (arg))
- mark_type_abi_tags (arg, val);
+ cp_walk_tree_without_duplicates (&arg, mark_abi_tags_r, &val);
}
}
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ /* A function's parameter types are part of the signature, so
+ we don't need to inherit any tags that are also in them. */
+ for (tree arg = FUNCTION_FIRST_USER_PARMTYPE (t); arg;
+ arg = TREE_CHAIN (arg))
+ cp_walk_tree_without_duplicates (&TREE_VALUE (arg),
+ mark_abi_tags_r, &val);
}
}
-/* Check that class T has all the abi tags that subobject SUBOB has, or
- warn if not. */
+/* Check that T has all the ABI tags that subobject SUBOB has, or
+ warn if not. If T is a (variable or function) declaration, also
+ add any missing tags. */
static void
check_abi_tags (tree t, tree subob)
{
- mark_type_abi_tags (t, true);
+ bool inherit = DECL_P (t);
+
+ if (!inherit && !warn_abi_tag)
+ return;
+
+ tree decl = TYPE_P (t) ? TYPE_NAME (t) : t;
+ if (!TREE_PUBLIC (decl))
+ /* No need to worry about things local to this TU. */
+ return;
+
+ mark_abi_tags (t, true);
tree subtype = TYPE_P (subob) ? subob : TREE_TYPE (subob);
- struct abi_tag_data data = { t, subob };
+ struct abi_tag_data data = { t, subob, error_mark_node };
+ if (inherit)
+ data.tags = NULL_TREE;
cp_walk_tree_without_duplicates (&subtype, find_abi_tags_r, &data);
- mark_type_abi_tags (t, false);
+ if (inherit && data.tags)
+ {
+ tree attr = lookup_attribute ("abi_tag", DECL_ATTRIBUTES (t));
+ if (attr)
+ TREE_VALUE (attr) = chainon (data.tags, TREE_VALUE (attr));
+ else
+ DECL_ATTRIBUTES (t)
+ = tree_cons (get_identifier ("abi_tag"), data.tags,
+ DECL_ATTRIBUTES (t));
+ }
+
+ mark_abi_tags (t, false);
+}
+
+/* Check that DECL has all the ABI tags that are used in parts of its type
+ that are not reflected in its mangled name. */
+
+void
+check_abi_tags (tree decl)
+{
+ if (TREE_CODE (decl) == VAR_DECL)
+ check_abi_tags (decl, TREE_TYPE (decl));
+ else if (TREE_CODE (decl) == FUNCTION_DECL
+ && !mangle_return_type_p (decl))
+ check_abi_tags (decl, TREE_TYPE (TREE_TYPE (decl)));
+}
+
+void
+inherit_targ_abi_tags (tree t)
+{
+ if (!CLASS_TYPE_P (t)
+ || CLASSTYPE_TEMPLATE_INFO (t) == NULL_TREE)
+ return;
+
+ mark_abi_tags (t, true);
+
+ tree args = CLASSTYPE_TI_ARGS (t);
+ struct abi_tag_data data = { t, NULL_TREE, NULL_TREE };
+ for (int i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
+ {
+ tree level = TMPL_ARGS_LEVEL (args, i+1);
+ for (int j = 0; j < TREE_VEC_LENGTH (level); ++j)
+ {
+ tree arg = TREE_VEC_ELT (level, j);
+ data.subob = arg;
+ cp_walk_tree_without_duplicates (&arg, find_abi_tags_r, &data);
+ }
+ }
+
+ // If we found some tags on our template arguments, add them to our
+ // abi_tag attribute.
+ if (data.tags)
+ {
+ tree attr = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t));
+ if (attr)
+ TREE_VALUE (attr) = chainon (data.tags, TREE_VALUE (attr));
+ else
+ TYPE_ATTRIBUTES (t)
+ = tree_cons (get_identifier ("abi_tag"), data.tags,
+ TYPE_ATTRIBUTES (t));
+ }
+
+ mark_abi_tags (t, false);
+}
+
+/* Return true, iff class T has a non-virtual destructor that is
+ accessible from outside the class heirarchy (i.e. is public, or
+ there's a suitable friend. */
+
+static bool
+accessible_nvdtor_p (tree t)
+{
+ tree dtor = CLASSTYPE_DESTRUCTORS (t);
+
+ /* An implicitly declared destructor is always public. And,
+ if it were virtual, we would have created it by now. */
+ if (!dtor)
+ return true;
+
+ if (DECL_VINDEX (dtor))
+ return false; /* Virtual */
+
+ if (!TREE_PRIVATE (dtor) && !TREE_PROTECTED (dtor))
+ return true; /* Public */
+
+ if (CLASSTYPE_FRIEND_CLASSES (t)
+ || DECL_FRIENDLIST (TYPE_MAIN_DECL (t)))
+ return true; /* Has friends */
+
+ return false;
}
/* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P,
if (!CLASSTYPE_LITERAL_P (basetype))
CLASSTYPE_LITERAL_P (t) = false;
- /* 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 (!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
derived class cannot have such a member automatically
/* Copy whatever these are holding today. */
TYPE_VFIELD (variants) = TYPE_VFIELD (t);
- TYPE_METHODS (variants) = TYPE_METHODS (t);
TYPE_FIELDS (variants) = TYPE_FIELDS (t);
}
}
if (!t)
return;
+ tree attrs = TYPE_ATTRIBUTES (t);
+ unsigned align = TYPE_ALIGN (t);
+ bool user_align = TYPE_USER_ALIGN (t);
+
for (variants = TYPE_NEXT_VARIANT (t);
variants;
variants = TYPE_NEXT_VARIANT (variants))
{
/* These are the two fields that check_qualified_type looks at and
are affected by attributes. */
- TYPE_ATTRIBUTES (variants) = TYPE_ATTRIBUTES (t);
- TYPE_ALIGN (variants) = TYPE_ALIGN (t);
+ TYPE_ATTRIBUTES (variants) = attrs;
+ unsigned valign = align;
+ if (TYPE_USER_ALIGN (variants))
+ valign = MAX (valign, TYPE_ALIGN (variants));
+ else
+ TYPE_USER_ALIGN (variants) = user_align;
+ TYPE_ALIGN (variants) = valign;
}
}
\f
/* Get the base virtual function declarations in T that have the
indicated NAME. */
-static tree
-get_basefndecls (tree name, tree t)
+static void
+get_basefndecls (tree name, tree t, vec<tree> *base_fndecls)
{
tree methods;
- tree base_fndecls = NULL_TREE;
int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
int i;
/* Find virtual functions in T with the indicated NAME. */
i = lookup_fnfields_1 (t, name);
+ bool found_decls = false;
if (i != -1)
for (methods = (*CLASSTYPE_METHOD_VEC (t))[i];
methods;
if (TREE_CODE (method) == FUNCTION_DECL
&& DECL_VINDEX (method))
- base_fndecls = tree_cons (NULL_TREE, method, base_fndecls);
+ {
+ base_fndecls->safe_push (method);
+ found_decls = true;
+ }
}
- if (base_fndecls)
- return base_fndecls;
+ if (found_decls)
+ return;
for (i = 0; i < n_baseclasses; i++)
{
tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (t), i));
- base_fndecls = chainon (get_basefndecls (name, basetype),
- base_fndecls);
+ get_basefndecls (name, basetype, base_fndecls);
}
-
- return base_fndecls;
}
/* If this declaration supersedes the declaration of
{
DECL_VINDEX (decl) = decl;
overrides_found = true;
+ if (warn_override && !DECL_OVERRIDE_P (decl)
+ && !DECL_DESTRUCTOR_P (decl))
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wsuggest_override,
+ "%q+D can be marked override", decl);
}
if (DECL_VIRTUAL_P (decl))
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype) = true;
}
else if (DECL_FINAL_P (decl))
- error ("%q+#D marked final, but is not virtual", decl);
+ error ("%q+#D marked %<final%>, but is not virtual", decl);
if (DECL_OVERRIDE_P (decl) && !overrides_found)
- error ("%q+#D marked override, but does not override", decl);
+ error ("%q+#D marked %<override%>, but does not override", decl);
}
/* Warn about hidden virtual functions that are not overridden in t.
tree fn;
tree name;
tree fndecl;
- tree base_fndecls;
tree base_binfo;
tree binfo;
int j;
have the same name. Figure out what name that is. */
name = DECL_NAME (OVL_CURRENT (fns));
/* There are no possibly hidden functions yet. */
- base_fndecls = NULL_TREE;
+ auto_vec<tree, 20> base_fndecls;
/* Iterate through all of the base classes looking for possibly
hidden functions. */
for (binfo = TYPE_BINFO (t), j = 0;
BINFO_BASE_ITERATE (binfo, j, base_binfo); j++)
{
tree basetype = BINFO_TYPE (base_binfo);
- base_fndecls = chainon (get_basefndecls (name, basetype),
- base_fndecls);
+ get_basefndecls (name, basetype, &base_fndecls);
}
/* If there are no functions to hide, continue. */
- if (!base_fndecls)
+ if (base_fndecls.is_empty ())
continue;
/* Remove any overridden functions. */
for (fn = fns; fn; fn = OVL_NEXT (fn))
{
fndecl = OVL_CURRENT (fn);
- if (DECL_VINDEX (fndecl))
+ if (TREE_CODE (fndecl) == FUNCTION_DECL
+ && DECL_VINDEX (fndecl))
{
- tree *prev = &base_fndecls;
-
- while (*prev)
/* If the method from the base class has the same
signature as the method from the derived class, it
has been overridden. */
- if (same_signature_p (fndecl, TREE_VALUE (*prev)))
- *prev = TREE_CHAIN (*prev);
- else
- prev = &TREE_CHAIN (*prev);
+ for (size_t k = 0; k < base_fndecls.length (); k++)
+ if (base_fndecls[k]
+ && same_signature_p (fndecl, base_fndecls[k]))
+ base_fndecls[k] = NULL_TREE;
}
}
/* Now give a warning for all base functions without overriders,
as they are hidden. */
- while (base_fndecls)
- {
- /* Here we know it is a hider, and no overrider exists. */
- 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);
- }
+ size_t k;
+ tree base_fndecl;
+ FOR_EACH_VEC_ELT (base_fndecls, k, base_fndecl)
+ if (base_fndecl)
+ {
+ /* Here we know it is a hider, and no overrider exists. */
+ warning (OPT_Woverloaded_virtual, "%q+D was hidden", base_fndecl);
+ warning (OPT_Woverloaded_virtual, " by %q+D", fns);
+ }
}
}
if (TREE_CODE (elt) != FIELD_DECL)
{
- if (complain)
+ /* We already complained about static data members in
+ finish_static_data_member_decl. */
+ if (complain && TREE_CODE (elt) != VAR_DECL)
{
if (is_union)
permerror (input_location,
parmlist = tree_cons (NULL_TREE, parms[i], parmlist);
tree fn = implicitly_declare_fn (sfk_inheriting_constructor,
t, false, ctor, parmlist);
+ gcc_assert (TYPE_MAIN_VARIANT (t) == t);
if (add_method (t, fn, NULL_TREE))
{
DECL_CHAIN (fn) = TYPE_METHODS (t);
one_inheriting_sig (t, ctor, new_parms, i);
if (parms == NULL_TREE)
{
- warning (OPT_Winherited_variadic_ctor,
- "the ellipsis in %qD is not inherited", ctor);
- inform (DECL_SOURCE_LOCATION (ctor), "%qD declared here", ctor);
+ if (warning (OPT_Winherited_variadic_ctor,
+ "the ellipsis in %qD is not inherited", ctor))
+ inform (DECL_SOURCE_LOCATION (ctor), "%qD declared here", ctor);
}
}
TYPE_HAS_COPY_ASSIGN (t) = 1;
TYPE_HAS_CONST_COPY_ASSIGN (t) = !cant_have_const_assignment;
CLASSTYPE_LAZY_COPY_ASSIGN (t) = 1;
- if (move_ok)
+ if (move_ok && !LAMBDA_TYPE_P (t))
CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 1;
}
/* When this goes into scope, it will be a non-local reference. */
DECL_NONLOCAL (x) = 1;
- if (TREE_CODE (t) == UNION_TYPE)
+ if (TREE_CODE (t) == UNION_TYPE
+ && cxx_dialect < cxx11)
{
- /* [class.union]
+ /* [class.union] (C++98)
If a union contains a static data member, or a member of
- reference type, the program is ill-formed. */
+ reference type, the program is ill-formed.
+
+ In C++11 this limitation doesn't exist anymore. */
if (VAR_P (x))
{
- error ("%q+D may not be static because it is a member of a union", x);
+ error ("in C++98 %q+D may not be static because it is "
+ "a member of a union", x);
continue;
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- error ("%q+D may not have reference type %qT because"
- " it is a member of a union",
- x, type);
+ error ("in C++98 %q+D may not have reference type %qT "
+ "because it is a member of a union", x, type);
continue;
}
}
CLASSTYPE_NON_AGGREGATE (t) = 1;
/* If at least one non-static data member is non-literal, the whole
- class becomes non-literal. Note: if the type is incomplete we
- will complain later on. */
- if (COMPLETE_TYPE_P (type) && !literal_type_p (type))
+ class becomes non-literal. Per Core/1453, volatile non-static
+ data members and base classes are also not allowed.
+ Note: if the type is incomplete we will complain later on. */
+ if (COMPLETE_TYPE_P (type)
+ && (!literal_type_p (type) || CP_TYPE_VOLATILE_P (type)))
CLASSTYPE_LITERAL_P (t) = false;
/* A standard-layout class is a class that:
CLASSTYPE_NON_STD_LAYOUT (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
-
- /* ARM $12.6.2: [A member initializer list] (or, for an
- aggregate, initialization by a brace-enclosed list) is the
- only way to initialize nonstatic const and reference
- members. */
- TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
- TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
+ if (cxx_dialect < cxx11)
+ {
+ /* ARM $12.6.2: [A member initializer list] (or, for an
+ aggregate, initialization by a brace-enclosed list) is the
+ only way to initialize nonstatic const and reference
+ members. */
+ TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
+ TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
+ }
}
type = strip_array_types (type);
/* Now that we've removed bit-field widths from DECL_INITIAL,
anything left in DECL_INITIAL is an NSDMI that makes the class
- non-aggregate. */
- if (DECL_INITIAL (x))
+ non-aggregate in C++11. */
+ if (DECL_INITIAL (x) && cxx_dialect < cxx14)
CLASSTYPE_NON_AGGREGATE (t) = true;
/* If any field is const, the structure type is pseudo-const. */
C_TYPE_FIELDS_READONLY (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT (t, 1);
-
- /* ARM $12.6.2: [A member initializer list] (or, for an
- aggregate, initialization by a brace-enclosed list) is the
- only way to initialize nonstatic const and reference
- members. */
- TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
- TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
+ if (cxx_dialect < cxx11)
+ {
+ /* ARM $12.6.2: [A member initializer list] (or, for an
+ aggregate, initialization by a brace-enclosed list) is the
+ only way to initialize nonstatic const and reference
+ members. */
+ TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
+ TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
+ }
}
/* A field that is pseudo-const makes the structure likewise. */
else if (CLASS_TYPE_P (type))
/* If this OFFSET is bigger than the MAX_OFFSET, then we should
stop. */
- if (max_offset && INT_CST_LT (max_offset, offset))
+ if (max_offset && tree_int_cst_lt (max_offset, offset))
return 0;
if (type == error_mark_node)
if (!TYPE_P (type))
{
- if (abi_version_at_least (2))
- type_binfo = type;
+ type_binfo = type;
type = BINFO_TYPE (type);
}
{
tree binfo_offset;
- if (abi_version_at_least (2)
- && BINFO_VIRTUAL_P (binfo))
+ if (BINFO_VIRTUAL_P (binfo))
continue;
- if (!vbases_p
- && BINFO_VIRTUAL_P (binfo)
- && !BINFO_PRIMARY_P (binfo))
- continue;
-
- if (!abi_version_at_least (2))
- binfo_offset = size_binop (PLUS_EXPR,
- offset,
- BINFO_OFFSET (binfo));
- else
- {
- tree orig_binfo;
- /* We cannot rely on BINFO_OFFSET being set for the base
- 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,
- offset,
- BINFO_OFFSET (orig_binfo));
- }
+ tree orig_binfo;
+ /* We cannot rely on BINFO_OFFSET being set for the base
+ 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,
+ offset,
+ BINFO_OFFSET (orig_binfo));
r = walk_subobject_offsets (binfo,
f,
binfo_offset,
offsets,
max_offset,
- (abi_version_at_least (2)
- ? /*vbases_p=*/0 : vbases_p));
+ /*vbases_p=*/0);
if (r)
return r;
}
- if (abi_version_at_least (2) && CLASSTYPE_VBASECLASSES (type))
+ if (CLASSTYPE_VBASECLASSES (type))
{
unsigned ix;
vec<tree, va_gc> *vbases;
{
tree field_offset;
- if (abi_version_at_least (2))
- field_offset = byte_position (field);
- else
- /* In G++ 3.2, DECL_FIELD_OFFSET was used. */
- field_offset = DECL_FIELD_OFFSET (field);
+ field_offset = byte_position (field);
r = walk_subobject_offsets (TREE_TYPE (field),
f,
/* 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)
- ? !INT_CST_LT (TYPE_MAX_VALUE (domain), index)
- : INT_CST_LT (index, TYPE_MAX_VALUE (domain)));
+ !tree_int_cst_lt (TYPE_MAX_VALUE (domain), index);
index = size_binop (PLUS_EXPR, index, size_one_node))
{
r = walk_subobject_offsets (TREE_TYPE (type),
/* If this new OFFSET is bigger than the MAX_OFFSET, then
there's no point in iterating through the remaining
elements of the array. */
- if (max_offset && INT_CST_LT (max_offset, offset))
+ if (max_offset && tree_int_cst_lt (max_offset, offset))
break;
}
}
offset zero. */
if (TREE_CODE (rli->t) == UNION_TYPE)
break;
- /* G++ 3.2 did not check for overlaps when placing a non-empty
- virtual base. */
- if (!abi_version_at_least (2) && binfo && BINFO_VIRTUAL_P (binfo))
- break;
if (layout_conflict_p (field_p ? type : binfo, offset,
offsets, field_p))
{
alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
if (!integer_zerop (BINFO_OFFSET (binfo)))
- {
- if (abi_version_at_least (2))
- propagate_binfo_offsets
- (binfo, size_diffop_loc (input_location,
+ propagate_binfo_offsets
+ (binfo, size_diffop_loc (input_location,
size_zero_node, BINFO_OFFSET (binfo)));
- 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. */
/*offsets=*/NULL,
/*max_offset=*/NULL_TREE,
/*vbases_p=*/true))
- {
- if (abi_version_at_least (2))
- CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
- else
- warning (OPT_Wabi,
- "class %qT will be considered nearly empty in a "
- "future version of GCC", t);
- }
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
}
/* We do not create a FIELD_DECL for empty base classes because
for (x = TYPE_METHODS (t); x; x = DECL_CHAIN (x))
{
check_for_override (x, t);
- if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x))
+ if (DECL_PURE_VIRTUAL_P (x) && (TREE_CODE (x) != FUNCTION_DECL || ! DECL_VINDEX (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))
+ if (TREE_CODE (x) == FUNCTION_DECL && DECL_VINDEX (x))
{
TYPE_POLYMORPHIC_P (t) = 1;
if (DECL_PURE_VIRTUAL_P (x))
clone = copy_decl (fn);
/* Reset the function name. */
DECL_NAME (clone) = name;
- SET_DECL_ASSEMBLER_NAME (clone, NULL_TREE);
/* Remember where this function came from. */
DECL_ABSTRACT_ORIGIN (clone) = fn;
/* Make it easy to find the CLONE given the FN. */
return clone;
}
+ SET_DECL_ASSEMBLER_NAME (clone, NULL_TREE);
DECL_CLONED_FUNCTION (clone) = fn;
/* There's no pending inline data for this function. */
DECL_PENDING_INLINE_INFO (clone) = NULL;
}
/* Note that this is an abstract function that is never emitted. */
- DECL_ABSTRACT (fn) = 1;
+ DECL_ABSTRACT_P (fn) = true;
}
/* DECL is an in charge constructor, which is being defined. This will
{
if (!TYPE_RAISES_EXCEPTIONS (TREE_TYPE (dtor)))
{
- tree ctx = DECL_CONTEXT (dtor);
- tree implicit_fn = implicitly_declare_fn (sfk_destructor, ctx,
- /*const_p=*/false,
- NULL, NULL);
- tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn));
+ tree eh_spec = unevaluated_noexcept_spec ();
TREE_TYPE (dtor) = build_exception_variant (TREE_TYPE (dtor), eh_spec);
}
}
return false;
}
-/* Returns true iff class T has a user-provided default constructor. */
+/* Returns true iff class T has a non-user-provided (i.e. implicitly
+ declared or explicitly defaulted in the class body) default
+ constructor. */
bool
-type_has_user_provided_default_constructor (tree t)
+type_has_non_user_provided_default_constructor (tree t)
{
tree fns;
- if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (t))
return false;
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
+ return true;
for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == FUNCTION_DECL
- && user_provided_p (fn)
+ && !user_provided_p (fn)
&& sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (fn)))
return true;
}
type = strip_array_types (type);
if (!CLASS_TYPE_P (type))
return type;
- if (type_has_user_provided_default_constructor (type))
+ if (!type_has_non_user_provided_default_constructor (type))
return NULL_TREE;
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, t); ++i)
DECL_INITIAL (*fieldsp).
check_bitfield_decl eventually sets DECL_SIZE (*fieldsp)
to that width. */
- && integer_zerop (DECL_SIZE (*fieldsp)))
+ && (DECL_SIZE (*fieldsp) == NULL_TREE
+ || integer_zerop (DECL_SIZE (*fieldsp))))
*fieldsp = DECL_CHAIN (*fieldsp);
else
fieldsp = &DECL_CHAIN (*fieldsp);
void
explain_non_literal_class (tree t)
{
- static struct pointer_set_t *diagnosed;
+ static hash_set<tree> *diagnosed;
if (!CLASS_TYPE_P (t))
return;
t = TYPE_MAIN_VARIANT (t);
if (diagnosed == NULL)
- diagnosed = pointer_set_create ();
- if (pointer_set_insert (diagnosed, t) != 0)
+ diagnosed = new hash_set<tree>;
+ if (diagnosed->add (t))
/* Already explained. */
return;
inform (0, " %q+T is not an aggregate, does not have a trivial "
"default constructor, and has no constexpr constructor that "
"is not a copy or move constructor", t);
- if (TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
- && !type_has_user_provided_default_constructor (t))
+ if (type_has_non_user_provided_default_constructor (t))
{
/* Note that we can't simply call locate_ctor because when the
constructor is deleted it just returns NULL_TREE. */
if (CLASS_TYPE_P (ftype))
explain_non_literal_class (ftype);
}
+ if (CP_TYPE_VOLATILE_P (ftype))
+ inform (0, " non-static data member %q+D has "
+ "volatile type", field);
}
}
}
TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t);
+ /* If the only explicitly declared default constructor is user-provided,
+ set TYPE_HAS_COMPLEX_DFLT. */
+ if (!TYPE_HAS_COMPLEX_DFLT (t)
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
+ && !type_has_non_user_provided_default_constructor (t))
+ TYPE_HAS_COMPLEX_DFLT (t) = true;
+
+ /* Warn if a public base of a polymorphic type has an accessible
+ non-virtual destructor. It is only now that we know the class is
+ polymorphic. Although a polymorphic base will have a already
+ been diagnosed during its definition, we warn on use too. */
+ if (TYPE_POLYMORPHIC_P (t) && warn_nonvdtor)
+ {
+ tree binfo = TYPE_BINFO (t);
+ vec<tree, va_gc> *accesses = BINFO_BASE_ACCESSES (binfo);
+ tree base_binfo;
+ unsigned i;
+
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ {
+ tree basetype = TREE_TYPE (base_binfo);
+
+ if ((*accesses)[i] == access_public_node
+ && (TYPE_POLYMORPHIC_P (basetype) || warn_ecpp)
+ && accessible_nvdtor_p (basetype))
+ warning (OPT_Wnon_virtual_dtor,
+ "base class %q#T has accessible non-virtual destructor",
+ basetype);
+ }
+ }
+
/* If the class has no user-declared constructor, but does have
non-static const or reference data members that can never be
initialized, issue a warning. */
if (LAMBDA_TYPE_P (t))
{
- /* "The closure type associated with a lambda-expression has a deleted
- default constructor and a deleted copy assignment operator." */
- TYPE_NEEDS_CONSTRUCTING (t) = 1;
- TYPE_HAS_COMPLEX_DFLT (t) = 1;
- TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
- CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 0;
-
/* "This class type is not an aggregate." */
CLASSTYPE_NON_AGGREGATE (t) = 1;
}
/* Collect the virtual functions declared in T. */
for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
- if (DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)
+ if (TREE_CODE (fn) == FUNCTION_DECL
+ && DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)
&& TREE_CODE (DECL_VINDEX (fn)) != INTEGER_CST)
{
tree new_virtual = make_node (TREE_LIST);
{
tree vbase;
tree t = rli->t;
- bool first_vbase = true;
tree *next_field;
if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) == 0)
return;
- if (!abi_version_at_least(2))
- {
- /* In G++ 3.2, we incorrectly rounded the size before laying out
- the virtual bases. */
- finish_record_layout (rli, /*free_p=*/false);
-#ifdef STRUCTURE_SIZE_BOUNDARY
- /* Packed structures don't need to have minimum size. */
- if (! TYPE_PACKED (t))
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), (unsigned) STRUCTURE_SIZE_BOUNDARY);
-#endif
- rli->offset = TYPE_SIZE_UNIT (t);
- rli->bitpos = bitsize_zero_node;
- rli->record_align = TYPE_ALIGN (t);
- }
-
/* Find the last field. The artificial fields created for virtual
bases will go after the last extant field to date. */
next_field = &TYPE_FIELDS (t);
if (!BINFO_PRIMARY_P (vbase))
{
- tree basetype = TREE_TYPE (vbase);
-
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
next_field = build_base_field (rli, vbase,
offsets, next_field);
-
- /* If the first virtual base might have been placed at a
- lower address, had we started from CLASSTYPE_SIZE, rather
- than TYPE_SIZE, issue a warning. There can be both false
- positives and false negatives from this warning in rare
- cases; to deal with all the possibilities would probably
- require performing both layout algorithms and comparing
- the results which is not particularly tractable. */
- if (warn_abi
- && first_vbase
- && (tree_int_cst_lt
- (size_binop (CEIL_DIV_EXPR,
- round_up_loc (input_location,
- CLASSTYPE_SIZE (t),
- CLASSTYPE_ALIGN (basetype)),
- bitsize_unit_node),
- BINFO_OFFSET (vbase))))
- 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;
}
}
}
continue;
offset = end_of_base (base_binfo);
- if (INT_CST_LT_UNSIGNED (result, offset))
+ if (tree_int_cst_lt (result, offset))
result = offset;
}
- /* G++ 3.2 did not check indirect virtual bases. */
- if (abi_version_at_least (2) && include_virtuals_p)
+ if (include_virtuals_p)
for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
vec_safe_iterate (vbases, i, &base_binfo); i++)
{
offset = end_of_base (base_binfo);
- if (INT_CST_LT_UNSIGNED (result, offset))
+ if (tree_int_cst_lt (result, offset))
result = offset;
}
CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
rli_size = rli_size_unit_so_far (rli);
if (TREE_CODE (rli_size) == INTEGER_CST
- && INT_CST_LT_UNSIGNED (rli_size, eoc))
- {
- if (!abi_version_at_least (2))
- /* In version 1 of the ABI, the size of a class that ends with
- a bitfield was not rounded up to a whole multiple of a
- byte. Because rli_size_unit_so_far returns only the number
- of fully allocated bytes, any extra bits were not included
- in the size. */
- rli->bitpos = round_down (rli->bitpos, BITS_PER_UNIT);
- else
- /* 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)));
+ && tree_int_cst_lt (rli_size, eoc))
+ {
+ /* 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,
type, then there are some special rules for allocating
it. */
if (DECL_C_BIT_FIELD (field)
- && INT_CST_LT (TYPE_SIZE (type), DECL_SIZE (field)))
+ && tree_int_cst_lt (TYPE_SIZE (type), DECL_SIZE (field)))
{
unsigned int itk;
tree integer_type;
bits as additional padding. */
for (itk = itk_char; itk != itk_none; ++itk)
if (integer_types[itk] != NULL_TREE
- && (INT_CST_LT (size_int (MAX_FIXED_MODE_SIZE),
- TYPE_SIZE (integer_types[itk]))
- || INT_CST_LT (DECL_SIZE (field),
- TYPE_SIZE (integer_types[itk]))))
+ && (tree_int_cst_lt (size_int (MAX_FIXED_MODE_SIZE),
+ TYPE_SIZE (integer_types[itk]))
+ || tree_int_cst_lt (DECL_SIZE (field),
+ TYPE_SIZE (integer_types[itk]))))
break;
/* ITK now indicates a type that is too large for the
integer_type = integer_types[itk];
} while (itk > 0 && integer_type == NULL_TREE);
- /* Figure out how much additional padding is required. GCC
- 3.2 always created a padding field, even if it had zero
- width. */
- if (!abi_version_at_least (2)
- || INT_CST_LT (TYPE_SIZE (integer_type), DECL_SIZE (field)))
+ /* Figure out how much additional padding is required. */
+ if (tree_int_cst_lt (TYPE_SIZE (integer_type), DECL_SIZE (field)))
{
- if (abi_version_at_least (2) && TREE_CODE (t) == UNION_TYPE)
+ if (TREE_CODE (t) == UNION_TYPE)
/* In a union, the padding field must have the full width
of the bit-field; all fields start at offset zero. */
padding = DECL_SIZE (field);
else
- {
- 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",
- t);
- padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
- TYPE_SIZE (integer_type));
- }
+ padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
+ TYPE_SIZE (integer_type));
}
-#ifdef PCC_BITFIELD_TYPE_MATTERS
+
/* An unnamed bitfield does not normally affect the
alignment of the containing class on a target where
PCC_BITFIELD_TYPE_MATTERS. But, the C++ ABI does not
was_unnamed_p = true;
DECL_NAME (field) = make_anon_name ();
}
-#endif
+
DECL_SIZE (field) = TYPE_SIZE (integer_type);
DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
DECL_USER_ALIGN (field) = TYPE_USER_ALIGN (integer_type);
field is effectively invisible. */
DECL_SIZE (field) = TYPE_SIZE (type);
/* We must also reset the DECL_MODE of the field. */
- if (abi_version_at_least (2))
- DECL_MODE (field) = TYPE_MODE (type);
- else if (warn_abi
- && DECL_MODE (field) != TYPE_MODE (type))
- /* Versions of G++ before G++ 3.4 did not reset the
- DECL_MODE. */
- warning (OPT_Wabi,
- "the offset of %qD may not be ABI-compliant and may "
- "change in a future version of GCC", field);
+ DECL_MODE (field) = TYPE_MODE (type);
}
else
layout_nonempty_base_or_field (rli, field, NULL_TREE,
empty_base_offsets);
/* Remember the location of any empty classes in FIELD. */
- if (abi_version_at_least (2))
- record_subobject_offsets (TREE_TYPE (field),
- byte_position(field),
- empty_base_offsets,
- /*is_data_member=*/true);
+ record_subobject_offsets (TREE_TYPE (field),
+ byte_position(field),
+ empty_base_offsets,
+ /*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
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
- && !abi_version_at_least (2)
- && !tree_int_cst_equal (DECL_FIELD_OFFSET (field),
- byte_position (field))
- && contains_empty_class_p (TREE_TYPE (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
last_field_was_bitfield = DECL_C_BIT_FIELD (field);
}
- if (abi_version_at_least (2) && !integer_zerop (rli->bitpos))
+ if (!integer_zerop (rli->bitpos))
{
/* Make sure that we are on a byte boundary so that the size of
the class without virtual bases will always be a round number
normalize_rli (rli);
}
- /* G++ 3.2 does not allow virtual bases to be overlaid with tail
- padding. */
- if (!abi_version_at_least (2))
- include_empty_classes(rli);
-
/* Delete all zero-width bit-fields from the list of fields. Now
that the type is laid out they are no longer important. */
remove_zero_width_bit_fields (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. */
- if (!abi_version_at_least (2) && CLASSTYPE_EMPTY_P (t))
- {
- 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 (OPT_Wabi,
- "layout of classes derived from empty class %qT "
- "may change in a future version of GCC",
- t);
- }
- else
- {
- tree eoc;
-
- /* If the ABI version is not at least two, and the last
- field was a bit-field, RLI may not be on a byte
- boundary. In particular, rli_size_unit_so_far might
- indicate the last complete byte, while rli_size_so_far
- indicates the total number of bits used. Therefore,
- rli_size_so_far, rather than rli_size_unit_so_far, is
- used to compute TYPE_SIZE_UNIT. */
- eoc = end_of_class (t, /*include_virtuals_p=*/0);
- TYPE_SIZE_UNIT (base_t)
- = size_binop (MAX_EXPR,
- convert (sizetype,
- size_binop (CEIL_DIV_EXPR,
- rli_size_so_far (rli),
- bitsize_int (BITS_PER_UNIT))),
- eoc);
- TYPE_SIZE (base_t)
- = size_binop (MAX_EXPR,
- rli_size_so_far (rli),
- size_binop (MULT_EXPR,
- convert (bitsizetype, eoc),
- bitsize_int (BITS_PER_UNIT)));
- }
+ /* Set the size and alignment for the new type. */
+ tree eoc;
+
+ /* If the ABI version is not at least two, and the last
+ field was a bit-field, RLI may not be on a byte
+ boundary. In particular, rli_size_unit_so_far might
+ indicate the last complete byte, while rli_size_so_far
+ indicates the total number of bits used. Therefore,
+ rli_size_so_far, rather than rli_size_unit_so_far, is
+ used to compute TYPE_SIZE_UNIT. */
+ eoc = end_of_class (t, /*include_virtuals_p=*/0);
+ TYPE_SIZE_UNIT (base_t)
+ = size_binop (MAX_EXPR,
+ convert (sizetype,
+ size_binop (CEIL_DIV_EXPR,
+ rli_size_so_far (rli),
+ bitsize_int (BITS_PER_UNIT))),
+ eoc);
+ TYPE_SIZE (base_t)
+ = size_binop (MAX_EXPR,
+ rli_size_so_far (rli),
+ size_binop (MULT_EXPR,
+ convert (bitsizetype, eoc),
+ bitsize_int (BITS_PER_UNIT)));
TYPE_ALIGN (base_t) = rli->record_align;
TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
this function until the end of the translation unit. */
for (method = TYPE_METHODS (type); method != NULL_TREE;
method = DECL_CHAIN (method))
- if (DECL_VINDEX (method) != NULL_TREE
+ if (TREE_CODE (method) == FUNCTION_DECL
+ && DECL_VINDEX (method) != NULL_TREE
&& ! DECL_DECLARED_INLINE_P (method)
&& ! DECL_PURE_VIRTUAL_P (method))
{
sorted_fields_type_new (int n)
{
struct sorted_fields_type *sft;
- sft = ggc_alloc_sorted_fields_type (sizeof (struct sorted_fields_type)
+ sft = (sorted_fields_type *) ggc_internal_alloc (sizeof (sorted_fields_type)
+ n * sizeof (tree));
sft->len = n;
determine_key_method (t);
/* If a polymorphic class has no key method, we may emit the vtable
- in every translation unit where the class definition appears. */
+ in every translation unit where the class definition appears. If
+ we're devirtualizing, we can look into the vtable even if we
+ aren't emitting it. */
if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)
keyed_classes = tree_cons (NULL_TREE, t, keyed_classes);
}
/* This warning does not make sense for Java classes, since they
cannot have destructors. */
- if (!TYPE_FOR_JAVA (t) && warn_nonvdtor && TYPE_POLYMORPHIC_P (t))
- {
- tree dtor;
-
- dtor = CLASSTYPE_DESTRUCTORS (t);
- if (/* An implicitly declared destructor is always public. And,
- if it were virtual, we would have created it by now. */
- !dtor
- || (!DECL_VINDEX (dtor)
- && (/* 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);
- }
+ if (!TYPE_FOR_JAVA (t) && warn_nonvdtor
+ && TYPE_POLYMORPHIC_P (t) && accessible_nvdtor_p (t)
+ && !CLASSTYPE_FINAL (t))
+ warning (OPT_Wnon_virtual_dtor,
+ "%q#T has virtual functions and accessible"
+ " non-virtual destructor", t);
complete_vars (t);
else
finish_struct_1 (t);
+ if (is_std_init_list (t))
+ {
+ /* People keep complaining that the compiler crashes on an invalid
+ definition of initializer_list, so I guess we should explicitly
+ reject it. What the compiler internals care about is that it's a
+ template and has a pointer field followed by an integer field. */
+ bool ok = false;
+ if (processing_template_decl)
+ {
+ tree f = next_initializable_field (TYPE_FIELDS (t));
+ if (f && TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE)
+ {
+ f = next_initializable_field (DECL_CHAIN (f));
+ if (f && same_type_p (TREE_TYPE (f), size_type_node))
+ ok = true;
+ }
+ }
+ if (!ok)
+ fatal_error (input_location,
+ "definition of std::initializer_list does not match "
+ "#include <initializer_list>");
+ }
+
input_location = saved_loc;
TYPE_BEING_DEFINED (t) = 0;
}
\f
/* Hash table to avoid endless recursion when handling references. */
-static hash_table <pointer_hash <tree_node> > fixed_type_or_null_ref_ht;
+static hash_table<pointer_hash<tree_node> > *fixed_type_or_null_ref_ht;
/* Return the dynamic type of INSTANCE, if known.
Used to determine whether the virtual function table is needed
else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
{
/* We only need one hash table because it is always left empty. */
- if (!fixed_type_or_null_ref_ht.is_created ())
- fixed_type_or_null_ref_ht.create (37);
+ if (!fixed_type_or_null_ref_ht)
+ fixed_type_or_null_ref_ht
+ = new hash_table<pointer_hash<tree_node> > (37);
/* Reference variables should be references to objects. */
if (nonnull)
if (VAR_P (instance)
&& DECL_INITIAL (instance)
&& !type_dependent_expression_p_push (DECL_INITIAL (instance))
- && !fixed_type_or_null_ref_ht.find (instance))
+ && !fixed_type_or_null_ref_ht->find (instance))
{
tree type;
tree_node **slot;
- slot = fixed_type_or_null_ref_ht.find_slot (instance, INSERT);
+ slot = fixed_type_or_null_ref_ht->find_slot (instance, INSERT);
*slot = instance;
type = RECUR (DECL_INITIAL (instance));
- fixed_type_or_null_ref_ht.remove_elt (instance);
+ fixed_type_or_null_ref_ht->remove_elt (instance);
return type;
}
tree fixed;
/* processing_template_decl can be false in a template if we're in
- fold_non_dependent_expr, but we still want to suppress this check. */
+ instantiate_non_dependent_expr, but we still want to suppress
+ this check. */
if (in_template_function ())
{
/* In a template we only care about the type of the result. */
return NULL_TREE;
}
+/* Return the outermost enclosing class type that is still open, or
+ NULL_TREE. */
+
+tree
+outermost_open_class (void)
+{
+ if (!current_class_type)
+ return NULL_TREE;
+ tree r = NULL_TREE;
+ if (TYPE_BEING_DEFINED (current_class_type))
+ r = current_class_type;
+ for (int i = current_class_depth - 1; i > 0; --i)
+ {
+ if (current_class_stack[i].hidden)
+ break;
+ tree t = current_class_stack[i].type;
+ if (!TYPE_BEING_DEFINED (t))
+ break;
+ r = t;
+ }
+ return r;
+}
+
/* Returns the innermost class type which is not a lambda closure type. */
tree
static tree
resolve_address_of_overloaded_function (tree target_type,
tree overload,
- tsubst_flags_t flags,
+ tsubst_flags_t complain,
bool template_only,
tree explicit_targs,
tree access_path)
target_type = build_reference_type (target_type);
else
{
- if (flags & tf_error)
+ if (complain & tf_error)
error ("cannot resolve overloaded function %qD based on"
" conversion to type %qT",
DECL_NAME (OVL_FUNCTION (overload)), target_type);
/* See if there's a match. */
if (same_type_p (target_fn_type, static_fn_type (instantiation)))
matches = tree_cons (instantiation, fn, matches);
-
- ggc_free (targs);
}
/* Now, remove all but the most specialized of the matches. */
if (matches == NULL_TREE)
{
/* There were *no* matches. */
- if (flags & tf_error)
+ if (complain & tf_error)
{
error ("no matches converting function %qD to type %q#T",
DECL_NAME (OVL_CURRENT (overload)),
if (match)
{
- if (flags & tf_error)
+ if (complain & tf_error)
{
error ("converting overloaded function %qD to type %q#T is ambiguous",
DECL_NAME (OVL_FUNCTION (overload)),
fn = TREE_PURPOSE (matches);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
- && !(flags & tf_ptrmem_ok) && !flag_ms_extensions)
+ && !(complain & tf_ptrmem_ok) && !flag_ms_extensions)
{
static int explained;
- if (!(flags & tf_error))
+ if (!(complain & tf_error))
return error_mark_node;
permerror (input_location, "assuming pointer to member %qD", fn);
if (fn == NULL)
return error_mark_node;
/* Mark all the versions corresponding to the dispatcher as used. */
- if (!(flags & tf_conv))
+ if (!(complain & tf_conv))
mark_versions_used (fn);
}
determining conversion sequences, we should not consider the
function used. If this conversion sequence is selected, the
function will be marked as used at this point. */
- if (!(flags & tf_conv))
+ if (!(complain & tf_conv))
{
/* Make =delete work with SFINAE. */
- if (DECL_DELETED_FN (fn) && !(flags & tf_error))
+ if (DECL_DELETED_FN (fn) && !(complain & tf_error))
+ return error_mark_node;
+ if (!mark_used (fn, complain) && !(complain & tf_error))
return error_mark_node;
-
- mark_used (fn);
}
/* We could not check access to member functions when this
if (DECL_FUNCTION_MEMBER_P (fn))
{
gcc_assert (access_path);
- perform_or_defer_access_check (access_path, fn, fn, flags);
+ perform_or_defer_access_check (access_path, fn, fn, complain);
}
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
- return cp_build_addr_expr (fn, flags);
+ return cp_build_addr_expr (fn, complain);
else
{
/* The target must be a REFERENCE_TYPE. Above, cp_build_unary_op
/* This function will instantiate the type of the expression given in
RHS to match the type of LHSTYPE. If errors exist, then return
- error_mark_node. FLAGS is a bit mask. If TF_ERROR is set, then
+ error_mark_node. COMPLAIN is a bit mask. If TF_ERROR is set, then
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.
function, or a pointer to member function. */
tree
-instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
+instantiate_type (tree lhstype, tree rhs, tsubst_flags_t complain)
{
- tsubst_flags_t flags_in = flags;
+ tsubst_flags_t complain_in = complain;
tree access_path = NULL_TREE;
- flags &= ~tf_ptrmem_ok;
+ complain &= ~tf_ptrmem_ok;
if (lhstype == unknown_type_node)
{
- if (flags & tf_error)
+ if (complain & tf_error)
error ("not enough type information");
return error_mark_node;
}
;
else
{
- if (flags & tf_error)
+ if (complain & tf_error)
error ("cannot convert %qE from type %qT to type %qT",
rhs, TREE_TYPE (rhs), fntype);
return error_mark_node;
deduce any type information. */
if (TREE_CODE (rhs) == NON_DEPENDENT_EXPR)
{
- if (flags & tf_error)
+ if (complain & tf_error)
error ("not enough type information");
return error_mark_node;
}
{
tree member = TREE_OPERAND (rhs, 1);
- member = instantiate_type (lhstype, member, flags);
+ member = instantiate_type (lhstype, member, complain);
if (member != error_mark_node
&& TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
/* Do not lose object's side effects. */
case OFFSET_REF:
rhs = TREE_OPERAND (rhs, 1);
if (BASELINK_P (rhs))
- return instantiate_type (lhstype, rhs, flags_in);
+ return instantiate_type (lhstype, rhs, complain_in);
/* This can happen if we are forming a pointer-to-member for a
member template. */
tree args = TREE_OPERAND (rhs, 1);
return
- resolve_address_of_overloaded_function (lhstype, fns, flags_in,
+ resolve_address_of_overloaded_function (lhstype, fns, complain_in,
/*template_only=*/true,
args, access_path);
}
case OVERLOAD:
case FUNCTION_DECL:
return
- resolve_address_of_overloaded_function (lhstype, rhs, flags_in,
+ resolve_address_of_overloaded_function (lhstype, rhs, complain_in,
/*template_only=*/false,
/*explicit_targs=*/NULL_TREE,
access_path);
case ADDR_EXPR:
{
if (PTRMEM_OK_P (rhs))
- flags |= tf_ptrmem_ok;
+ complain |= tf_ptrmem_ok;
- return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
+ return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
}
case ERROR_MARK:
if (! CLASS_TYPE_P (type))
return 0;
- /* In G++ 3.2, whether or not a class was empty was determined by
- looking at its size. */
- if (abi_version_at_least (2))
- return CLASSTYPE_EMPTY_P (type);
- else
- return integer_zerop (CLASSTYPE_SIZE (type));
-}
-
-/* Returns true if TYPE contains an empty class. */
-
-static bool
-contains_empty_class_p (tree type)
-{
- if (is_empty_class (type))
- return true;
- if (CLASS_TYPE_P (type))
- {
- tree field;
- tree binfo;
- tree base_binfo;
- int i;
-
- for (binfo = TYPE_BINFO (type), i = 0;
- BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
- if (contains_empty_class_p (BINFO_TYPE (base_binfo)))
- return true;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL
- && !DECL_ARTIFICIAL (field)
- && is_empty_class (TREE_TYPE (field)))
- return true;
- }
- else if (TREE_CODE (type) == ARRAY_TYPE)
- return contains_empty_class_p (TREE_TYPE (type));
- return false;
+ return CLASSTYPE_EMPTY_P (type);
}
/* Returns true if TYPE contains no actual data, just various
dump_class_hierarchy (tree t)
{
int flags;
- FILE *stream = dump_begin (TDI_class, &flags);
+ FILE *stream = get_dump_info (TDI_class, &flags);
if (stream)
{
dump_class_hierarchy_1 (stream, flags, t);
- dump_end (TDI_class, stream);
}
}
dump_vtable (tree t, tree binfo, tree vtable)
{
int flags;
- FILE *stream = dump_begin (TDI_class, &flags);
+ FILE *stream = get_dump_info (TDI_class, &flags);
if (!stream)
return;
dump_array (stream, vtable);
fprintf (stream, "\n");
}
-
- dump_end (TDI_class, stream);
}
static void
dump_vtt (tree t, tree vtt)
{
int flags;
- FILE *stream = dump_begin (TDI_class, &flags);
+ FILE *stream = get_dump_info (TDI_class, &flags);
if (!stream)
return;
dump_array (stream, vtt);
fprintf (stream, "\n");
}
-
- dump_end (TDI_class, stream);
}
/* Dump a function or thunk and its thunkees. */
if (!TARGET_VTABLE_USES_DESCRIPTORS)
init = fold_convert (vfunc_ptr_type_node,
build_fold_addr_expr (fn));
+ /* Don't refer to a virtual destructor from a constructor
+ vtable or a vtable for an abstract class, since destroying
+ an object under construction is undefined behavior and we
+ don't want it to be considered a candidate for speculative
+ devirtualization. But do create the thunk for ABI
+ compliance. */
+ if (DECL_DESTRUCTOR_P (fn_original)
+ && (CLASSTYPE_PURE_VIRTUALS (DECL_CONTEXT (fn_original))
+ || orig_binfo != binfo))
+ init = size_zero_node;
}
}
add_vcall_offset_vtbl_entries_1 (tree binfo, vtbl_init_data* vid)
{
/* Make entries for the rest of the virtuals. */
- if (abi_version_at_least (2))
- {
- tree orig_fn;
-
- /* The ABI requires that the methods be processed in declaration
- order. G++ 3.2 used the order in the vtable. */
- for (orig_fn = TYPE_METHODS (BINFO_TYPE (binfo));
- orig_fn;
- orig_fn = DECL_CHAIN (orig_fn))
- if (DECL_VINDEX (orig_fn))
- add_vcall_offset (orig_fn, binfo, vid);
- }
- else
- {
- tree derived_virtuals;
- tree base_virtuals;
- tree orig_virtuals;
- /* If BINFO is a primary base, the most derived class which has
- BINFO as a primary base; otherwise, just BINFO. */
- tree non_primary_binfo;
-
- /* 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 BINFO_VIRTUALS there that we need to consider. */
- non_primary_binfo = binfo;
- while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
- {
- tree b;
-
- /* If we have reached a virtual base, then it must be vid->vbase,
- because we ignore other virtual bases in
- add_vcall_offset_vtbl_entries_r. In turn, it must be a primary
- base (possibly multi-level) of vid->binfo, or we wouldn't
- have called build_vcall_and_vbase_vtbl_entries for it. But it
- might be a lost primary, so just skip down to vid->binfo. */
- if (BINFO_VIRTUAL_P (non_primary_binfo))
- {
- gcc_assert (non_primary_binfo == vid->vbase);
- non_primary_binfo = vid->binfo;
- break;
- }
-
- b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
- if (get_primary_binfo (b) != non_primary_binfo)
- break;
- non_primary_binfo = b;
- }
-
- if (vid->ctor_vtbl_p)
- /* For a ctor vtable we need the equivalent binfo within the hierarchy
- 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)));
- base_virtuals;
- base_virtuals = TREE_CHAIN (base_virtuals),
- derived_virtuals = TREE_CHAIN (derived_virtuals),
- orig_virtuals = TREE_CHAIN (orig_virtuals))
- {
- tree orig_fn;
-
- /* Find the declaration that originally caused this function to
- be present in BINFO_TYPE (binfo). */
- orig_fn = BV_FN (orig_virtuals);
-
- /* When processing BINFO, we only want to generate vcall slots for
- function slots introduced in BINFO. So don't try to generate
- one if the function isn't even defined in BINFO. */
- if (!SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), DECL_CONTEXT (orig_fn)))
- continue;
-
- add_vcall_offset (orig_fn, binfo, vid);
- }
- }
+ tree orig_fn;
+
+ /* The ABI requires that the methods be processed in declaration
+ order. */
+ for (orig_fn = TYPE_METHODS (BINFO_TYPE (binfo));
+ orig_fn;
+ orig_fn = DECL_CHAIN (orig_fn))
+ if (TREE_CODE (orig_fn) == FUNCTION_DECL && DECL_VINDEX (orig_fn))
+ add_vcall_offset (orig_fn, binfo, vid);
}
/* Add a vcall offset entry for ORIG_FN to the vtable. */