Revert "c++: Fix overeager Woverloaded-virtual with conversion operators [PR109918]"

This reverts commit 60163c8573.
This commit is contained in:
Simon Martin 2024-10-13 17:58:14 +02:00
parent f0f11559d5
commit a4eec6c712
8 changed files with 33 additions and 135 deletions

View file

@ -3243,15 +3243,10 @@ warn_hidden (tree t)
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;
@ -3269,63 +3264,47 @@ warn_hidden (tree t)
if (base_fndecls.is_empty ())
continue;
/* Find all the base_fndecls that are overridden, as well as those
that are hidden, in T. */
/* Remove any overridden functions. */
bool seen_non_override = false;
for (tree fndecl : ovl_range (fns))
{
fndecl = STRIP_TEMPLATE (fndecl);
bool any_override = false;
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& fndecl != conv_op_marker)
&& DECL_VINDEX (fndecl))
{
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. */
/* 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. */
for (size_t k = 0; k < base_fndecls.length (); k++)
{
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 (base_fndecls[k]
&& same_signature_p (fndecl, base_fndecls[k]))
{
base_fndecls[k] = NULL_TREE;
any_override = true;
}
}
if (!any_override)
seen_non_override = true;
}
if (warn_overloaded_virtual == 1
&& overriden_base_fndecls.elements () == num_fns)
/* All the fns override a base virtual. */
continue;
if (!seen_non_override && warn_overloaded_virtual == 1)
/* All the derived fns override base virtuals. */
return;
/* 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);
}
/* 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);
}
}
}

View file

@ -3397,8 +3397,7 @@ location_of (tree t)
return input_location;
}
else if (TREE_CODE (t) == OVERLOAD)
t = OVL_FIRST (t) != conv_op_marker ? OVL_FIRST (t)
: OVL_FIRST (OVL_CHAIN (t));
t = OVL_FIRST (t);
if (DECL_P (t))
return DECL_SOURCE_LOCATION (t);

View file

@ -5,12 +5,10 @@ class Foo
{
public:
virtual void f(int); // { dg-warning "hidden" }
void g(int); // Not virtual, so no warning
};
class Bar : public Foo
{
public:
virtual void f(short); // { dg-message "by" }
virtual void g(short);
};

View file

@ -1,12 +0,0 @@
// PR c++/109918 - Exact PR testcase
// { dg-do compile }
// { dg-additional-options -Wall }
struct A {
virtual operator int() { return 42; }
virtual operator char() = 0;
};
struct B : public A {
operator char() { return 'A'; }
};

View file

@ -1,12 +0,0 @@
// PR c++/109918 - PR testcase with -Woverloaded-virtual=2
// { dg-do compile }
// { dg-additional-options -Woverloaded-virtual=2 }
struct A {
virtual operator int() { return 42; }
virtual operator char() = 0;
};
struct B : public A {
operator char() { return 'A'; }
};

View file

@ -1,25 +0,0 @@
// PR c++/109918 - Test different CV-quals
// { dg-do compile }
// { dg-additional-options -Woverloaded-virtual }
struct A {
virtual operator char() { return 'a'; }
virtual operator char() const { return 'b'; } // { dg-warning "was hidden" }
virtual operator int() { return 42; }
};
struct B : public A {
operator char() { return 'A'; } // { dg-note "by" }
operator int() { return 43; }
};
struct AA {
virtual char func(char) { return 'a'; }
virtual char func(char) const { return 'b'; } // { dg-warning "was hidden" }
virtual int func(int) { return 42; }
};
struct BB : public AA {
char func(char) { return 'A'; } // { dg-note "by" }
int func(int) { return 43; }
};

View file

@ -1,15 +0,0 @@
// Identified when investigating PR c++/109918: no warning was emitted due to
// an incorrect early return in warn_hidden.
// { dg-additional-options -Wall }
struct Foo
{
virtual void f(int); // { dg-warning "hidden" }
virtual void g() {}
};
struct Bar : Foo
{
virtual void f(short); // { dg-message "by" }
virtual void g() {}
};

View file

@ -1,14 +0,0 @@
// PR c++/109918: Non virtual overloads in derived classes that don't override
// anything shouldn't cause warnings, even at -Woverloaded-virtual=2
// { dg-additional-options -Woverloaded-virtual=2 }
struct Foo
{
virtual void g() {}
};
struct Bar : Foo
{
virtual void g() {}
void g(int) {}
};