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

    <tr>
        <th>Summary</th>
        <td>
            Defaulted operator== generation fails if the default declaration is outside of the class definition and a operator== for a member can't be found using ADL
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

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

    <tr>
      <th>Reporter</th>
      <td>
          JoostHouben
      </td>
    </tr>
</table>

<pre>
    https://godbolt.org/z/xW3TTW7GY

This code is accepted by MSVC and GCC, but rejected by Clang. I believe it should be accepted.
```C++
namespace NS {
    struct S {
        int i;
    };
}

bool operator==(const NS::S& s1, const NS::S& s2) {
    return s1.i == s2.i;
}

class C {
public:
    NS::S s;

    bool operator==(const C&) const;
};

bool C::operator==(const C&) const = default;
```

If the `operator==(const NS::S& s1, const NS::S& s2)` is moved into `namespace NS` clang accepts it (ADL?):
https://godbolt.org/z/4Y3fq1hvn
```C++
namespace NS {
 struct S {
        int i;
    };

    bool operator==(const NS::S& s1, const NS::S& s2) {
        return s1.i == s2.i;
 }
}

class C {
public:
    NS::S s;

    bool operator==(const C&) const;
};

bool C::operator==(const C&) const = default;
```

Similarly, if the default declaration is moved into the body of `C`, clang also accepts it:
https://godbolt.org/z/Gzfcax7Gj
```C++
namespace NS {
 struct S {
        int i;
    };
}

bool operator==(const NS::S& s1, const NS::S& s2) {
    return s1.i == s2.i;
}

class C {
public:
    NS::S s;

    bool operator==(const C&) const = default;
};
```

Based on this wording from the [standard](https://timsong-cpp.github.io/cppwp/class.compare.default#1):

> Name lookups in the implicit definition ([[dcl.fct.def.default]](https://timsong-cpp.github.io/cppwp/dcl.fct.def.default)) of a comparison operator function are performed from a context equivalent to its [function-body](https://timsong-cpp.github.io/cppwp/dcl.fct.def.general#nt:function-body)[.](https://timsong-cpp.github.io/cppwp/class.compare.default#1.sentence-2) A definition of a comparison operator as defaulted that appears in a class shall be the first declaration of that function[.](https://timsong-cpp.github.io/cppwp/class.compare.default#1.sentence-3)

my understanding is that the definition of `operator==(const NS::S& s1, const NS::S& s2)` should be visible to the implicit definition of the defaulted `C::operator==` in all of the above three scenarios. As such, I think clang is incorrect in rejecting the first snippet.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzkV8uO27gS_Rp6U2hBoiw_Fl74cd03g0w2HUyQJUWWbCYUqZCU052vH5Tkh9xwJo1OZjYxBMkixcOqU6eKpAhB7yzighUrVmxGoo175xd_OBfi_11boh2VTj0t9jE2geVLxreMb3dOlc7ExPkd49tvjG8fP-Tv33-Y3n9k6Yaly_7-fq8DSKcQdAAhJTYRFZRP8OfDX2sQVsH9es34Gso2gsdPKI_9ayPsLoE3UKLReEDQEcLetUZBiWek5DjXJO2vNeMrurpWK2oMjZAI7x6ATY-tAAAh-lZGeNZKP20jaJYPWtl0c36n_wPnSucMuAa9iM6zfEMXn0lnQ4R3D0RVvnxgfAIhIxdvdXDG59dWeIyttxCyREOPCYEn-ns2SCNCgPUFo2lLoyXNcYY8TwnhAnPu_Scv1oxPyMLu7cqEa5wOY93P8hIo8gwUVqI1A9hTFIfIbyqIewQ2SX-eaDZJSYa1O6CiSDuCHaqEPpAkvKPAAqmO8dly85blW0I40fqjZBh_zKsv2f5gXyHQV6vzRSF9tTBfIk64qPP3kumDrrUR3jwRn7rX7HEgKJRGeBG1s8_kR19RbQVXQSeOSdrFo5egCW6gwxdL7_5bJcXj9P7Tfym937ow3pbJkJ5bklmJgAqchUhr5FfnlbY7qLyr-4pXrEIUVgmvWEETX8c96jo4u7uTTZPsdNy3ZaId41vZNF8bepL7iXR1IzwmJ-N4ng2r2PGe_w_eiRrBOPe5bQJo21mg68ZoqUnAlba60y_js26bsFLSJJWMhHxGLzavsfQWEp8Tua4CAb0LOjh7jgVUrZWdOcIjNOgr52tUPXc0wkZ8jIBfWn0QBm2E6EDHQJyeht5R3v2suTu06IVhPLeUn9fYfM6KVfJLY5cEtBGtxLsuPZbDyHyXLBFO2kQFcS8iiKZB4bs4C-jzJOyFMbSzosBX2ofrsuWqfuTJw3_Rs5yIG6izfoLWKvRdMlCG6NDbciyxA_9_2SbhstE86KBLg3As1rdSwl1Ve1R9Jb-1xtD2wwIRfRwjSncgyj0iBIlWeO1CAssAoZV7svINVQf7-bgkaIqZdN6jjATVb5iJlEvYgtVNgzEZqUWu5vlcjHCRTVOe8zSbpaP9IhNZjpUo1VhgMUOVZuW04lyl5QwLXpQjveApzzOeZdlsnKdpkkqZzcs5lgWfczku2DjFWmiTGHOoaeUZ6RBaXEyLdJaPjCjRhO40wbnFr9B1Ms7pcOEXNOaubHeBjVOjQwwXlKijwcXmTOQ1fdBnW8d5JbQJP1hnXRuDVnjiutf5IG50-BDP56goYaDGukQPUljGp5F0ULnWKmgDcb3cvB213jw_EPVyl65mfEsuHR93jXcUJca3HRGB8W1H1N8BAAD__wU4BkQ">