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

    <tr>
        <th>Summary</th>
        <td>
            Clang fails to export template specialization in C++20 if it's used in the same TU
        </td>
    </tr>

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

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

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

<pre>
    When building with `clang-cl.exe`, the following wouldn't export `foo<0>`. This works with MSVC `cl.exe`.
```
// a.cpp
struct A {
template <bool T > static bool __declspec(dllexport) foo();
//template<> bool __declspec(dllexport) foo<false>();
};

template <typename T>
T b() { return A::foo<false>() ? 1 : 0; }

template<> bool __declspec(dllexport) A::foo<false>() { return false; }

int main() {
   return b<int>();
}
```
No symbols are exported:
```
> clang-cl.exe a.cpp /c /std:c++20
> dumpbin /all a.obj | grep EXPORT
(empty stdout)
```
Removing `/std:c++20` from the cmd-line would export the specialization `foo<0>`.
Removing the commented-out specialization forward decl in the struct would export the specialization.
Moving the specialization before `b()` works too:
```
// a.cpp
struct A {
template <bool T > static bool __declspec(dllexport) foo();
};

template<> bool __declspec(dllexport) A::foo<false>() { return false; }

template <typename T>
T b() { return A::foo<false>() ? 1 : 0; }

int main() {
   return b<int>();
}
```
In the first example above, if `main()` doesn't call `b()` the specialization would be exported as well.

+@zmodem Since you've worked in this area in the past.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEVU2P2zYQ_TXjy2AFmpQl-aDDWrsGekhbJO7HLaCkkc2UIgWRWsf59QVFu956nTaXpoDgD4rz3hvyPVI6p_aGqITVBlZPCzn5gx1LuZeG5KK27an87UAG60npVpk9HpU_IGSs0dLsHxqd0GeCjAGv0B8IO6u1Pc4T7aRbAzz3SJ8HO_pQ1VkLomIgniFjCe4OyuHRjn-4iPvuw69VBD_DJsCegD0GgvjEv3wLfIsyaYYhjjg_To3HR4R8E0c89YOWnhBEVVurcYcgntF56VWD88jHjy012g3UAC9araNM4GsMMnkBfA1i85ryAgqiCmDfgCKqTmpHoeEbwPzp-vuNYn8ayMiecBcq59c7rCNE6BFH8tNo8BFEeO4xIYgtLhHEIzIQGwyEd9i-rZV_5LnKOb95Q6aMx14qc62I44iXyhpEpYy_v073PPCjRXfqa6sdypHOFqM26LxrGfGMry0bzYPAt034cD5UNsA3wDf8VU079UOtTJgjtUaZ2PoTQl7hfqQBn3__-af3u4tDCuoHf0LnWzuFVbsr5D319iXkYw7NG-KMYTfafs5S07cPWhmKUbqkKLwJW6SkVl-kV9a8DdYN1Qxm-56Mp_bBTv4WoLPjUY4thu1HZSJHjNS_cJ-p3l2JbqBr6uxIQeLZvqHFGHkfNH9lu_6HhH81kN8lIt83_f9BIH-ItunU6MKJL_tBE8ravlC4G1QXLHClDC5oLbl4QTQhW3-3yB0rRSvW17CjdHgkrZPXrYUopexLb1vq8YMyDeHJTsDzF5p9R210uJoPDnmx-yCdTxZtKdq1WMsFlct8ucxEztNscSizXBZiyXKZdylbM5EVgueFXDbUNquUFwtVcsZTJnixTNOcZ0nOVkXN16uM53VKnEHKqJdKJ1q_9Ikd9wvl3ERlka1XxULLmrSbL2HO53MKOA_38ViG-Q_1tHeQMq2cd1cEr7ymsgrTsZNKh0j9FdWLn24WURmsLqdN2BXlgecOJ3dZF0I3W--XxTTq8uD94ILN5kDulT9MddLYHvg2yDh_PQyj_USNB76du3LAt3NjfwYAAP__ztp78A">