diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2014-04-03 13:41:55 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2014-04-03 13:41:55 +0000 |
commit | 880a467be7f2b84126e19ea3f4d6872d5a3f1252 (patch) | |
tree | 8b8e9e063ebd4925080cfaaf28f2c840cedb712f /gcc/cp/class.c | |
parent | 0886676007c494d1a74efb0512d31f36171f3b0c (diff) | |
download | gcc-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.c | 80 |
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); |