<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">