<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/147374>147374</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [clang] Possibly incorrect -Winfinite-recursion emitted
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          baxter-huntington
      </td>
    </tr>
</table>

<pre>
    The following minimal examples are used as a reference: 

**Example A** (https://godbolt.org/z/5Mvbj7ePd):
```cpp
#include <string>
#include <iostream>

class Bar {
public:
    explicit Bar(const std::string aValue) : mValue{aValue} {};

    bool operator==(const std::string aValue) const { 
        std::cout << "bool operator==(const std::string aValue) const\n";
        return aValue == mValue; 
    };

    friend bool operator==(const std::string aLhs, Bar aRhs) { return aRhs == aLhs; }
 
private:
    std::string mValue;
};

int main() {
    auto other1 = Bar("Bar");
    [[ maybe_unused ]] auto equal = other1 == "Bar";
}
```

**Example B** (https://godbolt.org/z/aM5f8odqa):

```cpp
#include <string>
#include <iostream>

template<typename T>
class Foo {
public:
    explicit Foo(const T aValue) : mValue{aValue} {};

    bool operator==(const T aValue) const { 
        std::cout << "bool operator==(const T aValue) const\n";
        return aValue == mValue; 
    };

    friend bool operator==(const T aLhs, Foo aRhs) { return aRhs == aLhs; }
    
private:
 T mValue;
};

int main() {
    auto thing1 = Foo<std::string>("Foo");
    [[maybe_unused]] auto equal = thing1 == "Foo";
}
```

In Clang 21 (and the most recent trunk at the time of writing), **Example A** results in the following warning being emitted:
```
<source>:13:62: warning: all paths through this function will call itself [-Winfinite-recursion]
   13 |     friend bool operator==(const std::string aLhs, Bar aRhs) { return aRhs == aLhs; }
      | 
```

In older versions (e.g., Clang 20.1.0), no warning is emitted. `const`-qualifying `aRhs` resolves the warning in Clang 21. Is this a false positive? I'm not sure I understand what Clang deems to be infinitely recursive here.

Notably, when using a class template as in **Example B**, no warning is emitted. 
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy8Vt2O2zYTfRr6ZrCGTFmWdeEL_8TAAl8-BMGivSwoaWQxpUiHHNlxn74YSrbTjds0bZqFsKLM0TnzdzhSIeiDRVyJbCOy3UT11Dq_KtUnQv_U9pa0PZCzk9LVl9VLi9A4Y9xZ2wN02upOGcBPqjsaDKA8Qh-wBhVAgccGPdoKRboGkaz5kny9GexhfAQhly3RMYh0LeReyP3B1aUzNHX-IOT-NyH32dtT-SHHd7WQBZsla7FIhqs6HiNyqm1l-hpBpNtAXtuDSN98saNdII-qG_eSdWVUCLBRHkS-Ecn62JdGVwMHAAB-OhpdaWITIZeVs4EgUM0W6XogAvWTMj0KWQDH2g1P-Wb8Od9F7Hwn0s1AysClcwbcEb0i50W64-vr-MO-yDcwwvDfzbxyPXGUIt2CkPJfUIhsa4WUg8dXHo_UezuawgB4jTa9efQ60MZrtPW3xfu_Ngi5jWVR73ldxJivDrxvw5U-mjJ5vmM-rqDXJ0V4L-Fr9JvH7ONnzmpL0ClthVyOhCOA6smBoxb9jGnHVhBSxoWMPXm1jTraQKcuJf7S2ygHke1Ethtg8GOvTES5A_LTHe3m12dN_kg-m78vH_U2a5au_qju8vl-CiLsjiYmfEuXI1rVIbwMu4O49s59TVx7527N8PLd5fTyXwjoC9AfK5mXm0g4vd8mEmZ8rZOXfygLarU9DLLgInLn_EFt3AhRK7HEj7TyuVQeK-XOMSplxPpzpTxb2BplDyBnrA9la6AWoXOBwGOFloB8b38FRXGDdIfgGjh7zQOPvZTcAY_GlcfQGwqgbXz1Pg_Pylu-l8j_sdNEWL-aVrxOt8H1nufiG5GuZ6lI1wvJnT4C8FIZA0dFbQBqvesPLSchQNPbirSzcNbGQMVWmgKahnP59LO2jbaa8Mlj1fugneWExmTPUhD5Fn74gQxDf2_hYZGcqdHDCaOvgUuF08OUmcbyJdPZNBnLYd0txTpc8zsFPsGi_hbJE7eMbi5sIhZJ9HSRcMWcOWGI9bpB3FtkCs9hyK-CRpmAcHRBkz6hSPfwLGTegXUEofcIz9DbGn0gbqpzq2iEqRG7AOSgRLjWwVxgrMQJoUWP0yHy_ztSpblwUOcWLfQhJhmG8_J6oPJnlLbw8NT_i3xM6lVaF2mhJria5dmsmKWLopi0q2ZeVUWGRVY0i2JWq3qZyGxeyXmZN00mk4leyURmSZ7ks-V8lhbTplCLQs6lqrN6uVhKMU-wU9pMjTl1PF8mOoQeV7N5nubziVElmhA_JaWsOCus0mw38St-4ansD0HME6MDhTsEaTLx-3N4I9vBOxeCLs0FtK2c91gRPOrta8iT3pvVqxGoqe3LaeU6IffMNN6ejt59wIqE3EfPg5D70fnTSv4eAAD__1RQUCU">