aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/cp/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/cp/class.c')
-rw-r--r--gcc-4.9/gcc/cp/class.c121
1 files changed, 82 insertions, 39 deletions
diff --git a/gcc-4.9/gcc/cp/class.c b/gcc-4.9/gcc/cp/class.c
index b46391be1..334bfd5ee 100644
--- a/gcc-4.9/gcc/cp/class.c
+++ b/gcc-4.9/gcc/cp/class.c
@@ -149,6 +149,7 @@ static tree *build_base_field (record_layout_info, tree, splay_tree, 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 *);
@@ -1384,19 +1385,21 @@ find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
/* Otherwise we're diagnosing missing tags. */
else 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);
+ 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
{
- 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);
+ 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);
+ }
}
}
}
@@ -1476,6 +1479,33 @@ inherit_targ_abi_tags (tree t)
mark_type_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,
and NO_CONST_ASN_REF_P. Also set flag bits in T based on
properties of the bases. */
@@ -1512,13 +1542,6 @@ check_bases (tree t,
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
@@ -3062,9 +3085,9 @@ one_inherited_ctor (tree ctor, tree 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);
}
}
@@ -5547,6 +5570,30 @@ check_bases_and_members (tree t)
TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t);
+ /* 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. */
@@ -6597,25 +6644,11 @@ finish_struct_1 (tree t)
/* 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))
+ warning (OPT_Wnon_virtual_dtor,
+ "%q#T has virtual functions and accessible"
+ " non-virtual destructor", t);
complete_vars (t);
@@ -9017,6 +9050,16 @@ build_vtbl_initializer (tree binfo,
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;
}
}