aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2014-04-03 13:41:55 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2014-04-03 13:41:55 +0000
commit880a467be7f2b84126e19ea3f4d6872d5a3f1252 (patch)
tree8b8e9e063ebd4925080cfaaf28f2c840cedb712f /gcc/cp/class.c
parent0886676007c494d1a74efb0512d31f36171f3b0c (diff)
downloadgcc-880a467be7f2b84126e19ea3f4d6872d5a3f1252.zip
gcc-880a467be7f2b84126e19ea3f4d6872d5a3f1252.tar.gz
gcc-880a467be7f2b84126e19ea3f4d6872d5a3f1252.tar.bz2
invoke.texi (Wnon-virtual-dtor): Adjust documentation.
* doc/invoke.texi (Wnon-virtual-dtor): Adjust documentation. (Weffc++): Remove Scott's numbering, merge lists and reference Wnon-virtual-dtor. c-family/ * c.opt (Wnon-virtual-dtor): Auto set when Weffc++. cp/ * class.c (accessible_nvdtor_p): New. (check_bases): Don't check base destructor here ... (check_bases_and_members): ... check them here. Trigger on Wnon-virtual-dtor flag. (finish_struct_1): Use accessible_nvdtor_p. testsuite/ * g++.dg/warn/Wnvdtor.C: Add non-polymorphic case. * g++.dg/warn/Wnvdtor-2.C: New. * g++.dg/warn/Wnvdtor-3.C: New. * g++.dg/warn/Wnvdtor-4.C: New. * g++.dg/warn/Weff1.C: Delete. * g++.old-deja/g++.benjamin/15309-1.C: Delete. * g++.old-deja/g++.benjamin/15309-2.C: Delete. From-SVN: r209056
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r--gcc/cp/class.c80
1 files changed, 54 insertions, 26 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index d277e07..1dfcd91 100644
--- a/gcc/cp/class.c
+++ b/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 *);
@@ -1476,6 +1477,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 +1540,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
@@ -5547,6 +5568,27 @@ 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 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, base_binfo;
+ unsigned i;
+
+ for (binfo = TYPE_BINFO (t), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ {
+ tree basetype = TREE_TYPE (base_binfo);
+
+ if (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 +6639,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);