diff options
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r-- | gcc/cp/class.c | 111 |
1 files changed, 72 insertions, 39 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index d277e0758ee..334bfd5eee7 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 *); @@ -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); |