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

    <tr>
        <th>Summary</th>
        <td>
            [clang] C++20 Concept in Template Specialization Should Not See Protected Member.
        </td>
    </tr>

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

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

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

<pre>
    This bug exists in all released clang versions with C++20 support up to trunk.

The following code defined classes `Publ`/`Priv`/`Prot` with different visibility of member `x`, and inherit into a templated class `D` specialized by its accessibility using C++20 concept.
Boolean var `has` shows the specialization route.

In theory, only public member is visible, while protected/private are not.
These are checked by `static_assert`.

Clang mistakenly thinks protected member from `class Prot` is accessible, and failed to compile this code at the last static_assert, while any versions of gcc and msvc works.

Even more confusing, if we do the exact same thing again, with another class `Same` identical to `Prot`, but query the concept directly before template instantiation, clang will give opposite answer.

```cc
template<typename T> concept has_x = requires(T t){{ t.x };};

class Publ { public:    int x = 0; };
class Priv { private:   int x = 0; };
class Prot { protected: int x = 0; };
class Same { protected: int x = 0; };

template<typename T> class D;
template<typename T> requires ( has_x<T>) class D<T>: public T { public: static constexpr bool has = 1; };
template<typename T> requires (!has_x<T>) class D<T>: public T { public: static constexpr bool has = 0; };

// "Same" is identical to "Prot" but queried before used.
static_assert(!has_x<Same>,  "Protected should be invisible.");
static_assert(!D<Same>::has, "Protected should be invisible.");

static_assert( D<Publ>::has, "Public should be visible.");
static_assert(!D<Priv>::has, "Private should be invisible.");
static_assert(!D<Prot>::has, "Protected should be invisible.");  # clang failed here.

int main() { return 0; }
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0Vs2O4joTfRqzKQ0KDtCwYNHAtPQtvqsrNfuR41RI3XbsjF3hZ57-yg7pwKhH8yNdqUWL4Dp16tSpclQIdLSIG7HYisV-ojqund9c3sI3w2ZSuPK6OdQUoOiOgBcKHIAsKGPAo0EVsARtlD3CCX0gZwOciWvYCbkVciszCF3bOs_QtcAO2Hf2bSqyvcie-89DjVA5Y9yZ7BG0KxFKrMj2wCFgALHM_u4KI5aZkC_xi6fT3RfHYpn1aUuqKvRoGU4UqCBDfAVXQYNNgT4CXVLgDpQtgWyNnhjIsgMFjE1rFA-J4-l9RA4talKGvmEJxRWIAyitMbwn6EKkPpasndXY8q3MrXMGlYWTSgRqFRJo7c4BuMYRXjE5C951jA8K_c_Gc85fI29nzRXarjCkh6oo9NUajAfONRmE1jtGzVgK-dJ6OilGUB7BuoHWocbQP9M16re-NrHMAism_SUq76OwD1R2qdUNBVZvGJlwTfYtjOkGTpV3TUTrlRx6RKNyPdnYhUqRwTKaQ7umjeQ5Gi45QXGSyKjA8EjsvVJlr6P3XAVHrRNsE04azs6_hYcKPp_QQuNi2c5WqXMRiyo4I5QupcOL0gxBNYmKPYI6KrIpZTSZso5r9KNLXlWDqbwSLZNWJhYzWjMGFh3D1w79NSW4GQRK8qjZXKHAKlIaHAhkAyvLlCwR4_sZO5MxcKQTgmtbFyg21YYz-ocSY8r0p3X_YIAV-Y6vLdpY2EHkn9951Cp8uYDI9-Dxa0ceg5CrA7CQa_G0FU9b4OkFxNNe5Nvb512-W4-7wkA82ptT5M8AEEcLeuRM5Fu4Dx6sQac-rHdpH_cLYY5vYYPR8-efh8VO_VbYzwRMqOPxHx4cdAUhV73cIt_FX4Rcjyj9k_x5GPDDd4L2IxDbFhgvrYfCORPhEvnZ9-R_iY2Qs_-Izw_EjGtbvoCQMs2NlHEtPI6OlGl0pHyfG4r7qR-SLmB58_t3K-G-loQdy9nBgNcvqFC7zkQwIHtbm1MhZbT6wPMD2P0dZP4s8ue4xuXut6E_TpC0TlfcB_C99CP275FOd-VHpPs74c_VSB36YzViU_LbVrtdADX6x3svjmWTFu8qujJazyN33o7Oetx3k3KTl-t8rSa4mT3ls3k2z2bzSb1Z43yR6cVyneercqnWGrXWOJfzOWotZ3JCG5nJ-Ww2k9k6z_P5dLXQlZovZ1WZrReLfC3mGTaKzNSYUzN1_jihEDrczGaLVb6aGFWgCcNLlN_EU5-K7hjEPDPxpWmMY2KTXrdS8WKxv3tx2N32MVk4DFfB6-PrwWuv6l-O4RURRrn_ny7e6aTzZlMztyF2Jo3akbjuiql2jZAvkcft36fWu39Qs5AvqZgg5MutntNG_hsAAP__l7UueA">