<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/83409>83409</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
clang: initialization with assignment expression possibly triggers wrong template instantiation
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
bebuch
</td>
</tr>
</table>
<pre>
```cpp
template <typename T>
struct holder {
holder() = default;
constexpr ~holder() {
static_assert(sizeof(T) || true);
}
};
struct Incomplete;
struct Class {
Class();
~Class();
holder<Incomplete> a{}; // Reject: MSVC; Accept: GCC, clang
holder<Incomplete> b = {}; // Reject: MSVC, GCC; Accept: clang
holder<Incomplete> c = holder<Incomplete>{}; // Reject: MSVC, GCC, clang
};
int main() {
[[maybe_unused]] Class v;
}
```
Live Code: [Case `a`](https://godbolt.org/z/cYWTTMeoa), [Case `b`](https://godbolt.org/z/xf45795b1), [Case `c`](https://godbolt.org/z/Y764zPqKa).
I assume that all 3 cases should be valid in C++20/23, but I'm not sure.
Note that this compiles fine with MSVC and GCC, only clang reject:
```cpp
template <typename T>
struct holder {
holder() = default;
constexpr ~holder() {
static_assert(sizeof(T) || true);
}
};
struct Incomplete;
template <typename=void> // make Class a template
struct Class {
Class();
~Class();
holder<Incomplete> a{};
holder<Incomplete> b = {};
holder<Incomplete> c = holder<Incomplete>{};
};
int main() {
[[maybe_unused]] Class v;
}
```
[Live Code](https://godbolt.org/z/1so75fa5x)
There are these Bug reports to MSVC:
- https://developercommunity.visualstudio.com/t/10514504
- https://github.com/microsoft/STL/issues/4417
- https://developercommunity.visualstudio.com/t/10604135
And this one to GCC:
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114076
Note comment from Jiang An:
> I don't see why there's even a temporary value [in case `c`] since C++17. The prvalue is used to initialize the data member (via temporary materialization). The potential invocation of destructor should be in the body of constructors.
I also asked about this at StackOverflow:
- https://stackoverflow.com/questions/78040562
The original `holder` class template was `std::unique_ptr`, which became `constexpr` in C++23.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsV01v20gS_TWtSyEC2SRF86CDREUL7ya7i4kwg5yMJlkke9LsZvpDinzIbx80SVu0LTjOzByHMGCAVXyvqqvqVYsZwxuJuCbJliS7BXO2VXpdYOHKdlGo6rwmq2D8K_ueBDsSbCx2vWAWgUS5PfcoWYdwINH70WysdqWFVokKNZB0O74GgOkdoTeEZkCiHVRYMycsiSanybVU0lj81mv4_vSTOZh_jGWWl3fMGNSW0BvD71HVhN4cRvecpDlY7ZDQ7JEESLqb6NLdM-op-FtZqq4XaPG6PRfMmKfhDK_GOC9M36-9fXEeUT7new_MAw-hwdWH0D2he_gFf8fSkmgDHz_9mj_z3pQl9oPxX3lOaA6lYLL5IXUxlOXCf52K5gPqI-OF7G0s5cBy3fhG7qcZvSwklxY6xuW1zhmafduxc4F3TjqDFUl2JNlNZT1eoB4b5WEI5hQf-BEhVxX62EiyzZlBIKuAeb9kR-hNa21vSLQZM2lUVShhl0o3hO7vCd2Xn387HD6iYr49aD4HKd4M8q2OkzRLivAlSPlmkM_pKr7__9f_-EiW8yRvgRnjOgTbMgtMCIigZAYNmFY5UUGBcGSCV8Al5IRuCd3SgNA9jXwwhbNwS2jagVQWjNP4BP2_yk7ItuUGfBtwgQZqLhFO3LZDzYHJ6qHoSorzWHnQD40xR_xHrub2a7mTaHdUvPJzOE1Yx77g1PsMHj75U3oH8Krk_VDvflafXsd9k8z8tID8TepBku1FQN40o6FRaVKz5Js_2RnSoUWNwLSfJDQIW-dno1faGrBqWg5PhuQdPOWq8IhC9ahL1XVOcnteHrlxTBjrKq6WpeoI3VsfQ5CEcRLE13EabltXTO4dL7UyqvaffTp8IHTPjXFoCN3HcZj-9UhWQRxGyTyvjaxGIVESferDkno186Ysl4100ykXrrnnQjBC96ZVp7vCNcuy4STa-3nZhWEcpKsX-uVDRWmh1qqDf3MvTRv5XJai93ALlZKEphYMIpzas6-XRkJTA3hEOQ2f0kyfvaY69L3G5aC3MzkHw2WJD2Ibpks4tAi9Hj_hBnxP-vS55JYzwe-HzoCKWQYddoXXOXpz5HO-jlnUgzOz3IeZTbDKovQowOVRlYMRVA0VjtKg9GwRcDkQ-Xuj9xl0cXQyz5eKMAqY-YIVsEK5Sf-ZhU-WlV_-d0RdC3X6QfGM91WT79QaXx0aH6Nvs_QmiINkRZ8NCyjNGy6Z8Gc6qcMq8EvFmEf5gxMz3m5s5fmijZP8q8O73npnv4lOLS9bKLD0-8RX52ELeLDZMoyWi2odVVmUsQWuwzTIaLAKgnDRrpMwLqqoDIssiOuyrlmGFBlindE6rSpc8DUNaBxQmoUhXcXhMquiNIpTGmcsjKK4IHGAHeNiKcSx8128GIZsfRPFQbYQrEBhhss9peN1iVJ_z9dr7_-ucI0hcSC4seaCYLkVuB7do82li8baD1t5_N0wdL3PGI3xpl4ZwwtxBqt506A2cNJKNpcz5dJY5rvJIy2cFutX9MPHM_1712s17PqZhgwZ_hEAAP__R5_Bsg">