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

    <tr>
        <th>Summary</th>
        <td>
            CUDA: Host-side static class member leaks into PTX as extern global
        </td>
    </tr>

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

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

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

<pre>
    Consider the following bit of code:
```c++
template <class _Elem>
class codecvt {
    static int id;
};

template <class _Elem>
int codecvt<_Elem>::id;

template class codecvt<char>;
```
Including this into a CUDA file (you don't even have to use the class in a device-side function or variable) leads to warnings like `ptxas warning : Unresolved extern variable '_ZN7codecvtIcE2idE' in whole program compilation, ignoring extern qualifier` or, when compiling with `-fgpu-rdc`, errors like these at link time: `nvlink error : Undefined reference to '_ZN7codecvtIcE2idE'`. The resulting PTX contains this line: `.extern .global .align 4 .u32 _ZN7codecvtIcE2idE;`.

This code pattern with the static member of a template class plus explicit instantiation appears several times throughout Microsoft's STL implementation, which e.g. makes it impossible to `#include <locale>` (and various other headers) when using CUDA on Windows. The code above was reduced from https://github.com/microsoft/STL/blob/vs-2019-16.9/stl/inc/xlocale.

Godbolt: https://godbolt.org/z/n1jzMrMqd

When compiling with `-O1`, the `GlobalOptPass` eliminates the unused variable from the device code and the problem goes away. NVCC does not show this issue, it never generates `.extern .global` symbols for host-side static class members. Clang appears to only be generating these extraneous `.extern .global` symbols for code that exactly follows the above pattern; eliminating the templates or even replacing the explicit instantiation with implicit instantiation makes the problem go away.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyMVUtv2zgQ_jX0ZWBBpmIrOviQOHG3QF9A0-1iLwUljiU2FKlyKDvpr18MpSRNt-kuYCARH_P4HkNFZFqHuBXrS7G-Wqgxdj5s-9sxeLeovb7f7rwjozFA7BAO3lp_Mq6F2kTwB2i8RlFciPxK5Bdik0-_RshL_qXViP1gVUQQxa6xigi-XFvsRXE97U9rHKg5RhDlfA0AgKKKpgHjIhgtinlHlFdP__-vFBxgTiCK3eNecSGKix8DPw_2rDCO3KmQrl3-1O70-do1dtSMTewMcdEeFOw-XV3AwVgEIc_v_QjaOyHLCHhEB506IkQPI2HCd0ppHCjQeDQNLhl7OIyuicY78AGOKhhVWxSyAotKE98_qeCMawmsuUUQm3yId4oelkEUF_DJBSRvj6gB7yIG9xgJhCy__P2unDt93VxLo6-FLLmQU-ctwhB8G1QPje8HYxXXIuQOTOt84ARzxG-jsuZgMIhNDj7wkVOHbr7GB08mdlzf8tAO4zLohuGTO8AQfJjLjx0SgopgjbuFaHpWGF9yx7SSzs49aTwYhxoCHjCgaxKaL_UjNnkGNx1CQBpt5Ho-3PwFjXdRGUcTb9a4h3zZ3FbWWl8rC5mypnVwBtlYSPhFiuKSb_0ophsOyadgUDEFSwgw17O4e-xrDOwlBT9Jb7AjAd4N1jQmgnEUlYsmoQ9qGFAFAsIjBmUTTNxB8GPb-THCW9MET_4QhSwJPt68AdMPFnt08ZG_U2eaDjBrM-jVLRJwmn7wRIZ1wVAyPYVJ0k72sr5RFtkGm5wlrZxOQvIjgY8dBuhQaQzE-kzkj8RAJx94B5-N0_5EEw8JGFX7I8JJEQTUY4MaDsH30MU4EFtU7oXctyZ2Y501vhdy3z-1tv9480bIfW19LeT-SEuZr6rlapNVQu4pWiH3xjVC7u-mwp-R88rr2tvIbP-UbdrIfGiF3H8Xcu9WX7-_DW-_6R_vf35B2-9Xs6qZZrHJXyX5vB_iB0XEuKE1vXEqJsYQRjcS6ic_pv55Y5oBM0xOp7Uh-NpiD61HAnVS9xm8-3O3A83fzkegzp_mEUQ0YvJpBMc6gRYdhpT33_Lmwui-r70lOPgAnac4jZ9ZqZMoJ71SBjurXPuow-jBO3sPNT4kmSYhWxnvYlAOWSL_nTY1GzsVAe9UE-39_OhMUE1imb0kistHKOdsjxYinpVpxgYcrGoe9l-wU-KODfKLvckaz7GfkF_obaGrolIL3K5Kma9ltd5Ui26bl-fntZT5YV3n52dFKeuqwKKS1aqpdaXLhdnKXJ7lZV6t5FqeVVld1EqXmOuyKlabTS7OcuyVsZm1x56FuEhsbqvz1Xq1sKpGS-nVltLh6YFqyY942PKdZT22JM5yayjSU5RoosUtu5Fl_8fvOObn5XZ-yHhOKnqY8xNzizHY7W9syjnnP8sh-K_YsGFTpSTkfurkuJX_BAAA__-Fu9k0">