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

    <tr>
        <th>Summary</th>
        <td>
            [clang-repl] JIT linkage issues with extern templates
        </td>
    </tr>

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

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

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

<pre>
    ## Overview
Hey folks! I've found that the clang interpreter on the latest 19 build cannot link to extern templates definitions. I have verified that this bug also existed in `release/18.x`, so it's not new to 19.

Pinging @vgvassilev for vis, since I originally reported this to him with a more complex repro case.

## Test case
This requires linking to an extern template which is defined either within the current process or in a loaded shared library. In my test case, I follow the existing pattern of shared object loading to build a shared object containing our defined function. You can see the patch to add the test here:

```diff
diff --git a/clang/test/Interpreter/Inputs/extern-template.cpp b/clang/test/Interpreter/Inputs/extern-template.cpp
new file mode 100644
index 000000000000..e08263a96c8f
--- /dev/null
+++ b/clang/test/Interpreter/Inputs/extern-template.cpp
@@ -0,0 +1,3 @@
+#include <cstdio>
+
+char foo(char c) { printf("good %c", c); return c; }
diff --git a/clang/test/Interpreter/Inputs/extern-template.hpp b/clang/test/Interpreter/Inputs/extern-template.hpp
new file mode 100644
index 000000000000..ac067a202dc8
--- /dev/null
+++ b/clang/test/Interpreter/Inputs/extern-template.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+template <typename T> T foo(T t) { return t; }
+
+extern template char foo(char c);
diff --git a/clang/test/Interpreter/extern-template.cpp b/clang/test/Interpreter/extern-template.cpp
new file mode 100644
index 000000000000..edb586285bdf
--- /dev/null
+++ b/clang/test/Interpreter/extern-template.cpp
@@ -0,0 +1,16 @@
+// REQUIRES: host-supports-jit, x86_64-linux
+
+// To generate libextern-template.so :
+// clang -xc++ -o Inputs/libextern-template.so -fPIC -shared Inputs/extern-template.cpp
+
+// RUN: cat %s | env LD_LIBRARY_PATH=%S/Inputs:$LD_LIBRARY_PATH clang-repl -Xcc -I%S/Inputs | FileCheck %s
+// RUN: cat %s | env LD_LIBRARY_PATH=%S/Inputs:$LD_LIBRARY_PATH clang-repl -Xcc -I%S/Inputs -Xcc -O2 | FileCheck %s
+
+extern "C" int printf(const char* format, ...);
+
+#include "extern-template.hpp"
+
+%lib libextern-template.so
+
+foo('a');
+// CHECK: good
```

The output of running this test (after having compiled `libextern-template.so`):

```
❯ ./bin/llvm-lit -j1 -v ../clang/test/Interpreter/extern-template.cpp
llvm-lit: /home/jeaye/projects/third-party/llvm-project/llvm/utils/lit/lit/llvm/config.py:509: note: using clang: /home/jeaye/projects/third-party/llvm-project/build/bin/clang
-- Testing: 1 tests, 1 workers --
FAIL: Clang :: Interpreter/extern-template.cpp (1 of 1)
******************** TEST 'Clang :: Interpreter/extern-template.cpp' FAILED ********************
Exit Code: 1

...

JIT session error: Symbols not found: [ _Z3fooIcET_S0_ ]
error: Failed to materialize symbols: { (main, { __orc_init_func.incr_module_15, $.incr_module_15.__inits.0 }) }
error: Failed to materialize symbols: { (main, { __orc_init_func.incr_module_15 }) }
/home/jeaye/projects/third-party/llvm-project/clang/test/Interpreter/extern-template.cpp:16:11: error: CHECK: expected string not found in input
// CHECK: good

...

********************
********************
Failed Tests (1):
  Clang :: Interpreter/extern-template.cpp
Testing Time: 0.05s
Total Discovered Tests: 1
  Failed: 1 (100.00%)
```

## Additional notes
In the `Inputs/extern-template.hpp` file, we have this line:

```cpp
extern template char foo(char c);
```

If it is instead changed to this, the test will pass:

```cpp
char foo(char c);
```

## Real world example
My test case is reduced down from a real world use case I originally noticed in the fmt library: https://github.com/fmtlib/fmt/blob/b61c8c3d23b7e6fdf9d44593877dba1c8a291be1/include/fmt/format.h#L4283
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEWN1u47gVfhrm5kCCRNmSfeELx4mxbqfdacYLdHtjUNSRxRmKVEnKSfr0BSnFThzPbJPMooYhSPw5_Hh-P5JZK_YKcUGm12R6c8V612iz-IrsEa9KXT0uCM0IzeDXA5qDwHuS3JBk-Qs-Qq3lN0toChtCiwNCrXtVgWuYA9cgcMnUHoRyaDqDDg1oFTokc2gdpHMoeyEr4Ewp7UAK9Q2cBnxwaBQ4bLswEiqshRJOaGVj2EDDDggHNKIWeFxOWCj7PTBpvQBhHVYgFJA8MSiRWSR0nc7iB5InhK7AahCO0MKCX1nhvV84ncfD5obnZ6H2Qu2BTJLD_uD1JPEAtTZwEDYIEYojbEAbsReKSfkIBjttXIAlrJfZiBbuhWuAQasNAtdtJ_HBDzQaOLP4Ys1R11uvH985tG69MIP_7oVBG_TkcTkNTJ1rC-4bwRsQo9awAhSuQRNAiEH_vDcGlYPOaI7WgjZeVQykZhVWYBtmsAIpSsPMYwwbBe0juCMkuoKNt73U90FcULcH1DEXsOj6SYYuvyJ3QfCIeLA4OxvAtXJMKD9G9-YIve4V92aP4XfdezcBixjW7JjjTdBAVYWGAK9BgyRbvlBongz_StT10OTfIIr2wgEjdB3clNC1l0DoenPy1_DV9c4Suh7UHD2pOeZdB-VHZg9YvOfVQiK0ukJIkySfTIYeoSp8gOTZL44xmdE8Y_Ocz8a9RFEEhK4rPBC6Vr2UT250Pfx_BkYyScgkgcgHTgKEXqeErjIYmp-tlwnFZV8hkGzFrauEJtntqf_phTfMQK01obPwygmdAymuoTNCuZrQGaF0r3UFhE45odQ7nB9Esmsw6HqjgPt3Utz8RIM2HzJo8z6DMp7kBaMJrfjsTzdo80ODTi8YtDNs3zLQiuNrOx4zDslW7rFDxVqELcluYTuadwvuybaj3dwLuz2Xdp7GLnkJya7fbvB3Be7PiteqnM5yOpuW1U-L17eFaZq_Nuua0DXc3f7jt83d7ReSLaHR1kW273zpstFXXxhX8DDLd_kkkkL1D6_NNUrZatijQuMtJkV5js1qOKXj46SBF0QPfNxypOHos5eFRPXnzQqisWb8DxnrNdK73_7ut8qZ82nFAilWgOoAn252nzbXd8u733efl9tfSHZD6PTLKYyyJaGTs0HDDiKDnYTon5xDtHkxKQhfC4mrBvm3sN7_Fc7Q-Cv9Ia6zQCSUrgilnr6dEjPXypOAhhlCl54JtSz4ShzHz8PzpfpPZYHSSymJ0kuzplKUl13q9eghTRBaMEKLcyCDvle_3K7-6jXuC8sZM3hOF7YNgu5d1zvPYkyvAicZyJxnGITOWO2pbMMOvsfTOSGx8kTzMlrPN-ffIyXj5y0l8xuyXENM6LoUygeCPLSRFA6irylEB_AafmdieBLlt0_outGtJ8OB4BO67oz2FMzHk2uEqaKOGff4hGDsHT8JXfdOyCFQ3ek5dHGtarGPu0eSLaeJ37Mn156QQW-DsgL8D6EI9PGopEHgmFgDaRbDAmmwViDpKdxr8w2NhSgahq6Xm09-0CrkIW-abAl_XDQInaXeKVJvz9G93v-H7e2XLRBavA0FoQV4_Lc38JHVB_y3D8LBSlfBROlzB_UB_ezzL5stWLRWaAVojDZ-wpfHttRyOECFk1-w7PQadv_Kaq03_Ha7-5LsgEzHcn-cuWYhZJyGljk0gknxHwQ7yAtSimuv7pZ5K6_C526nDd_5Y-DOnwpiobjZtbrqJe7SaRhFJ2et8S5MsHESOEegIn8-lldrvd_b3xzv2TLN_SP1yI97PCY_fOiQ-9OpdcYH5NF0_vwnfLE4Iv5e0rzkHh_3xI9LGO3oc4ANofo868IbY32sBUM-ga1oQ4QkcfJUMLfaMQk3wnJ9QPO07rMwgtGxhmTk8SRJnCSETk_Z41L9Gc__y6oK9x1MhhQ6rroZju8kT37I8fMkUFTvrfc43JaEAiaF-u7p-LjpN_Hwi1vY1CAcCAtCWYes8iLUfogxj8PjOp7Y74WU0DFr_xDY24GMurxDJn0NkBXgA2s7OZ5l_vbsTgPC_UrVc6yg0vcKaqNbYGBOc3uLw9AX9z1KO8GHqya_p7p1T_cmgVg71w2czcfTXrimL2OufbGsWydFObz4eia1_yjzlM94VtGsLDCvq3peTSbTeTYriqpkKZ8xOk9LTAldj6zqKGFgY3FDaPZpQmfZVbXIqnk2Z1e4SIt0nmeU0uKqWeTpZJ5lHGlRzMqUzma0qHKWzTFLk4IlxZVY0IROkpzOkywrkiKepnWZpvNiMsGM0jmSSYItEzL26SrWZn8lrO1xMS_SrLiSrERpw3Uipf68FDo9zZveXJlFSHFlv7dkkkhhnT1JccLJcA95IrRkegO--kihvrE9DrLscKN2fk941Ru5-IHKR5pylmMHiYSuB_SHBf1vAAAA__8fVF0z">