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

    <tr>
        <th>Summary</th>
        <td>
            [clang] [clangd] Missing information about explicit instantiation of function template
        </td>
    </tr>

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

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

    <tr>
      <th>Reporter</th>
      <td>
          16bit-ykiko
      </td>
    </tr>
</table>

<pre>
    ```cpp
namespace test {
template <typename T>
void foo() {}
}

struct X {};

template void test::f^oo<X>();
```

Currently, if trigger go-to-definition at the location of `^`, clangd will give no response. And the tokens in the explicit instantiation are 
 also not highlighted. After some investigation, I found that the underlying cause is that the Clang frontend doesn't store the information about explicit instantiation of function templates.
 
 Dump the AST of above code

 ```cpp
 |-NamespaceDecl 0xd083678 <<source>:1:1, line:4:1> line:1:11 test
| `-FunctionTemplateDecl 0xd0838e8 <line:2:1, line:3:13> col:6 foo
| |-TemplateTypeParmDecl 0xd083708 <line:2:11, col:20> col:20 typename depth 0 index 0 T
|   |-FunctionDecl 0xd083838 <line:3:1, col:13> col:6 foo 'void ()'
|   | `-CompoundStmt 0xd0839c8 <col:12, col:13>
|   `-FunctionDecl 0xd083d18 <col:1, col:13> col:6 foo 'void ()' explicit_instantiation_definition
|     |-TemplateArgument type 'X'
| | `-RecordType 0xd083aa0 'X'
|     |   `-CXXRecord 0xd0839f8 'X'
| `-CompoundStmt 0xd0839c8 <col:12, col:13>
`-CXXRecordDecl 0xd0839f8 <line:6:1, col:11> col:8 referenced struct X definition
  ```

As you can see, the decl from explicit instantiation is only added to its semantic context but not to its lexical context.

If use a visitor to further explore:

```cpp
bool VisitFunctionTemplateDecl(clang::FunctionTemplateDecl* decl) {
 for(auto spec: decl->specializations()) {
 spec->getLocation().dump(srcMgr);
 spec->getFunctionTypeLoc().getReturnLoc().getLocalSourceRange().dump(srcMgr)
 spec->getQualifierLoc().getSourceRange().dump(srcMgr);
        auto info = spec->getTemplateSpecializationInfo();
 info->PointOfInstantiation.dump(srcMgr);
        llvm::outs() << info->TemplateArguments << "\n";
        llvm::outs() << info->TemplateArgumentsAsWritten << "\n";
    }
    return true;
}
```

The output is 
```
test.cpp:3:6
<test.cpp:3:1>
<<invalid sloc>>
test.cpp:8:21
0x564cf04d7560
0x0
```

Only instantiation point is recorded correctly, all other information is from primary template. But for explicit specializations, the information is recorded properly. 

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysV1Fv4zYM_jXKC5HAkZLGfchD6rZAgbvd7VpsfTsoEu1oJ0uGJGfNfv0g2U6cpLfbcCvaxLLI7yMpkmK596oyiGuyvCPL-wlvw8669fxmq8L08E19s5OtlYc1ucm6X9E0JLsn2cbwGn3DBUJAH4Cs7rr3AetG84BAWBEODUY5eCHsodveWyWhtJbQnNDbpLa677ZOD-nTB9eKAK-DDLsb7x5pEmA0gbANYZuSLB-sJax4jZSJ5KQ5ODEGKlrn0AR9ILQAVUJwqqrQQWWnwU4llsqooKwBHiDsELQVPK1tCRFq-RA_aQFCc1NJ-FNpDZXaIxgLDn1jjccZbIxM6sF-Q-NBmbTCt0YroQIo4wM3QXXQ3CF01gHX3oKxAXaq2mlV7QLKGWzKgA68rRGU2aMPqkqa0Y4nKG2b2HqLWyPR6YMyFQjeegTlT5tFtBpKZ01AI0Fa9IbQVQAfrMMkokxpXd1btrVt-J7ZtoSyNSI9D-fjZ70j_dd9WzcJdfP8EhX41u4RhJU4PhS4zjcgq2L6y5B09yg0ZG8yy9nNKo-5RljhbesExnNnm3n6owVoZZCwzaJ79zCs0_68S5w--4rIOn3sPXjpHRgx5ZiYegR6wcDimkUKYTVhm5uU5ifsVTEdMF8ODX7mrh5hr7Ir7ATeYdHshEszONaVxCbsIANlJL5BBi8nPkiMgzdjL9iYiQ1edOBXDgChq1RifS3R1QVFClph6yYm3XOoQ09zKxJND0svKM5ARlEf2SnnY4D_ZOIxQb-eJejXUzWP-eHsbDauams0IQU5Qr-e-Tx4_AWFdTIeZG8u59m1dA_eO1m8vnZqQ4jK_B2CnwjnmGMUycRzPPGbi3DOT-HMwWGJDo1ACcf-exk1gHcb6cbDwbYguAGPGAlimctoRuls_b2moTxYow_ApUQJwYIKHjzWUUKAiH3pLcC2DakL9vsa35Tgetieje14KiE2OQ575VWwLuqUrQs7dMkG62IUxhrXzWZrrYbfov577YDQPDX77sZ5X2KTPB-uuC5upXWE5rwNFnyDgrBOaErYQ1wrrtVfKSh-yOSxdhSJohWGD_0d1InNZFs3hObeiY-VG194Y52jmYcGP1jRq1YYvmBonTl7FfH1c-qmX7ip8Hs8VyS_tlyrUqE7g_sXSEeL-58UpHjxAGH3Y4Yhys9nAXsypb247JN2VPpslQmfyqdx1v3YAK33dXe-tg1-mFbSNXNEvmwZfhAglJJlYeLX_4K78b87FQKaHxAcJ6i4cOlcIbgWTxPQccR6r4Jfdgi2DU0bYlW-Kxjvy1ksk-7muOmFWHGxMT81pWSxMnuulQSvrUgX9MMVXh7vtnn3Ontb3ixEmS3kajlQZ2_ZP9j-KfaQ887SxIOPnrjUEFGCsM6h6Gc9rjXY1BXGA47yXbdqnKq5OxznmBnctSFW8KmPXdVscTUujckbZ5s4h836yE7kmslbdssnuJ6v2DxjOV1kk926LCWXq22ODDPOFttsW1JG2UIs5Jby7Hai1jSji_k8yzO2XNFsxrIsXyxWknEsb8vbnCwyrLnSs5htM-uqifK-xfV8vlzM84nmW9R-GPndOkpNt23lySLTygd_0gsq6PTPQdfwlvcwPMu4-Ki8j3PlT42Ik9bp9S6ExsfCoI-EPlYq7NrtTNia0MdUMt3XtHH2DxSB0MfkkSf0sXdqv6Z_BwAA__9I6-A2">