https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104603

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2022-03-01
                 CC|                            |msebor at gcc dot gnu.org

--- Comment #8 from Martin Sebor <msebor at gcc dot gnu.org> ---
It looks like the problem is that the call to Base::operator==() might enter
infinite recursion.  With the changed test case below GCC issues
-Winfinite-recursion pointing it out.  With the original test case the infinite
recursion isn't inevitable but because it can't be ruled out GCC emits
(invalid) code that then triggers -Warray-bounds.  It might be possible to do
better: detect the possible infinite recursion early and fold the equality to
false.  (As far as I can see, that's what recent Clang seems to do.)

$ cat pr104603.C && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout
pr104603.C
struct Base {
  bool isX_;
  Base(bool isX = false) : isX_(isX) { }
  bool isX() const { return isX_; }
  bool operator==(const Base& rhs) const;
};

struct X : public Base {
  X(const Base& b) : Base(true), b_(b) { }
  bool operator==(const X& rhs) const { return b_ == rhs.b_; }
  Base b_;
};

inline bool Base::operator==(const Base& rhs) const
{
    return /* isX() && rhs.isX() && */ static_cast<const X&>(*this) ==
static_cast<const X&>(rhs);
}

Base base (true);

int main ()
{
  return X(base) == X(base);
}
pr104603.C: In member function ‘bool X::operator==(const X&) const’:
pr104603.C:10:8: warning: infinite recursion detected [-Winfinite-recursion]
   10 |   bool operator==(const X& rhs) const { return b_ == rhs.b_; }
      |        ^~~~~~~~
In member function ‘bool Base::operator==(const Base&) const’,
    inlined from ‘bool X::operator==(const X&) const’ at pr104603.C:10:51:
pr104603.C:16:69: note: recursive call
   16 | rn /* isX() && rhs.isX() && */ static_cast<const X&>(*this) ==
static_cast<const X&>(rhs);
      |                               
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~


;; Function main (main, funcdef_no=9, decl_uid=2452, cgraph_uid=10,
symbol_order=10) (executed once)

Merging blocks 3 and 4
int main ()
{
  <bb 2> [local count: 10631108]:

  <bb 3> [local count: 1073741824]:
  goto <bb 3>; [100.00%]

}

Reply via email to