continue;
tree name = OVL_NAME (fns);
+ size_t num_fns = 0; /* The number of fndecls in fns. */
auto_vec<tree, 20> base_fndecls;
tree base_binfo;
tree binfo;
unsigned j;
+ hash_set<tree> overriden_base_fndecls;
+ /* base_fndecls that are hidden but not overriden. The "value"
+ contains the fndecl that hides the "key". */
+ hash_map<tree, tree> hidden_base_fndecls;
if (IDENTIFIER_CDTOR_P (name))
continue;
if (base_fndecls.is_empty ())
continue;
- /* Remove any overridden functions. */
- bool seen_non_override = false;
+ /* Find all the base_fndecls that are overridden, as well as those
+ that are hidden, in T. */
for (tree fndecl : ovl_range (fns))
{
- bool any_override = false;
+ fndecl = STRIP_TEMPLATE (fndecl);
if (TREE_CODE (fndecl) == FUNCTION_DECL
- && DECL_VINDEX (fndecl))
+ && fndecl != conv_op_marker)
{
- /* If the method from the base class has the same
- signature as the method from the derived class, it
- has been overridden. Note that we can't move on
- after finding one match: fndecl might override
- multiple base fns. */
+ num_fns++;
+ tree fndecl_vindex = DECL_VINDEX (fndecl);
+ /* If the method from the base class has the same DECL_VINDEX
+ as the method from the derived, it has been overridden.
+ Note that we can't move on after finding one match: fndecl
+ might override multiple base fns. */
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;
- any_override = true;
- }
+ {
+ if (!base_fndecls[k] || !DECL_VINDEX (base_fndecls[k]))
+ continue;
+ tree base_fndecl_vindex = DECL_VINDEX (base_fndecls[k]);
+ if (fndecl_vindex
+ && !tree_int_cst_compare (fndecl_vindex,
+ base_fndecl_vindex))
+ overriden_base_fndecls.add (base_fndecls[k]);
+ else if (IDENTIFIER_CONV_OP_P (name)
+ && (DECL_NAME (fndecl)
+ != DECL_NAME (base_fndecls[k])))
+ /* If base_fndecl[k] and fndecl are conversion operators
+ to different types, they're unrelated. */
+ ;
+ else
+ hidden_base_fndecls.put (base_fndecls[k], fndecl);
+ }
}
- if (!any_override)
- seen_non_override = true;
}
- if (!seen_non_override && warn_overloaded_virtual == 1)
- /* All the derived fns override base virtuals. */
- return;
+ if (warn_overloaded_virtual == 1
+ && overriden_base_fndecls.elements () == num_fns)
+ /* All the fns override a base virtual. */
+ continue;
- /* Now give a warning for all base functions without overriders,
- as they are hidden. */
- for (tree base_fndecl : base_fndecls)
- if (base_fndecl)
- {
- auto_diagnostic_group d;
- /* Here we know it is a hider, and no overrider exists. */
- if (warning_at (location_of (base_fndecl),
- OPT_Woverloaded_virtual_,
- "%qD was hidden", base_fndecl))
- inform (location_of (fns), " by %qD", fns);
- }
+ /* Now give a warning for all hidden methods. Note that a method that
+ is both in hidden_base_fndecls and overriden_base_fndecls is not
+ hidden. */
+ for (auto hidden_base_fndecl : hidden_base_fndecls)
+ {
+ tree hidden_fndecl = hidden_base_fndecl.first;
+ tree hider = hidden_base_fndecl.second;
+ if (!hidden_fndecl
+ || overriden_base_fndecls.contains (hidden_fndecl))
+ continue;
+ gcc_assert (hider);
+ auto_diagnostic_group d;
+ if (warning_at (location_of (hidden_fndecl),
+ OPT_Woverloaded_virtual_,
+ "%qD was hidden", hidden_fndecl))
+ inform (location_of (hider), " by %qD", hider);
+ }
}
}