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

    <tr>
        <th>Summary</th>
        <td>
            Include-cleaner: instantiated template bodies should not (usually) be traversed
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang-include-cleaner
      </td>
    </tr>

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

    <tr>
      <th>Reporter</th>
      <td>
          sam-mccall
      </td>
    </tr>
</table>

<pre>
    consider this template:

```
template <class T>
int get() { return T::value; }
```

Here the definition of `get()` itself clearly isn't a reference to `Foo::value`, even if we later instantiate `get<Foo>`.
(Usually instantiating `get<Foo>` means mentioning `Foo` somewhere and so `Foo.h` will end up being included.)

So we want to walk the body of `get<T>` (the "templated function") but not `get<Foo>` (the "implicit template specialization").

---

This hasn't been a really obvious problem, because normally one of the following applies:
 - the template is in a header, so its instantiation is not in the main file, so we already don't walk it
 - the template is in the main file, and so is the instantiation site, and between them it's reasonable to consider Foo::value used
 - the template is in the main file (which is a header), and the instantiation sites are in other files => not in this TU => we already don't walk them

However we can avoid all these cases and still have this problem:

```
// dispatch.h
template <class Getter>
int dispatch() {
  return Getter::template get<A>;
}

// main.cc
struct MyGetter {
  template <class T> int get() { return T::value; }
}
int v = dispatch<MyGetter>();
```

Here, `MyGetter::get<A>()` is defined in `main.cc`, and (indirectly) instantiated from `main.cc`, and yet the reference to `A::value` can't reasonably be associated with `main.cc` since the `A` is only mentioned in `dispatch.h`.

(This seems ridiculous, but is extracted from real code).

---

The most direct solution is to avoid walking functions (and classes, and variables, and aliases, and concepts?) that were instantiated from templates. This might lead to missing references we were previously finding, which would be a regression.

I think we should probably do this first, understand the fall-out, and then deliberately work out heuristics for when it's OK to traverse the instantiated bodies.

A less-direct idea is just preventing instantiation in the first place using SkipFunctionBodies like in clangd, but I don't think this really works: we don't always have full control over the parse (e.g. if embedded in a clang-tidy check), and not all templates are skippable functions (e.g. classes, auto-typed functions).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJycVl1v47oR_TX0y8CGQsWO_eCHbHbdLoq2D3dv3ylybPGGIgUOZdX99cVQH5bT7LYoEDi2NF9n5vAMFZG9eMSj2H4RUv7DJvW3LggpxfbrSnWpDvFIqlk3WivnVlUwt6MOnqzBCKm2BAmb1qmEonwVxVdRTJ-7YvzLPycrEOWbdooIfojy2_DO-gQXTELuhTyAePkCEVMXPZu8ivL1qlyHovwC4uXrp8GHzz9jREg1gsGz9TbZ4CGcQeyKObjYFWAToTuDdqiiu4ElL-RLAgURzxjRa4QU2OsUwjL_rhDyDfCKHuwZegSGE8F6Ssonm7ENqcq37PpN7IrNWKDc_06dcpxvtrf-8okHNKg8QYOeAYw2_HZXAIUG-5phKm-Apio3Nb_srXOA3kDXQoXsaL12nUGzYeSLRv0WuPxe-cRIe-Xec9t4touGlW8_xoqE3PN7IeU0RQPnzmsukJkiD1B1CXxIn-G5e9umdVbbNFMGqEVtlbP_UvdYm2Wp6_V6-fMHE65W48gqRJ_nlhsbqqsNHUEbQ-Ww4WFVqFVHCD7EZrDxyAi5nnNwLvTcJtW2ziLN_IV1NpiLtASW89SoDEaOS4FZtBxl8GzGHbA-ezfKejhbh6N9j6BcRGVuYMJQfm68Tb9K-h-RxrnzsavxQwFk02xTYeq5O6nGhnPIF-I-UfCqcpng8yF-pDl0hOZ_LomH29dW1_zy3qHDVMbnRRKoyM8hpBpjDkQgyq-i_HZvoSX48fv09GfdY3gPEhB6vGJke608qGuwBpRzbEj8jDg59zDxaanVFYdUE2l-qWFCnoQ8gbHUqqTrTf0zafsTpoTxQd8mp7vIjU2etG7y4UnMEYez9MqRytHhroHLmngiG62HZ5RipxP89TbEXCb7XIbh_1Dg6Qu7XnlOd4jl25SaCx-Edy7_Z8rNlBG74u7JeRf47_pNg8CjYaKIXTFhHwSapyvk3npjI-rkboxoIdIGzjE0n_vdMGXKftwEr497gLmVOTifqBtUCIoo6CFFb1P9mALI5ng1DgEHIMG72yT1M54Fv-4LZFojWQEJsSGI1ljdudBR1roucUT8Z4pKzzBZG0EHg_9VWBGaQMxT7hpQcN2kaimMB4mPHAvmpP3Ejea-ZSYhTW28qmhZZuYHylm1eK-D19gmEuWJh5NqlaDHiJ-MaeIrbSAjb-ylTuBQGS6rsURc0DwvyouNQ7UR8zpwNzgzF_yFsw9a1YfOmTwxiHiJSGSDf-jOd1YF_87RqM7WLBB50CYMinG2kRLH7LzByHUPcndWzq1DlxYS6MGgsxVGldDdoA_xHUKXoMYuWkpWE5xDhJ4tR63--18YX4rqipHwg46i4V1tkR5qfgWHROtxgNag4uH90VHKzWCS5TvBw84a9DxjgdYpzfrPZr-92_Y0jvlLzgXOvmfR1k75i5ko930W5KFjuTfjRmagvFa5jZOVcr260aC8584xOX2KwUG45gslQqsYsZB73Fw2fNXCpkJjhuOhhvTrZM0NdI36fbFteHdksZ9Ik_cMvdu2zVvvgbc5-pK4XQrrdGsXdxviQ7Myx9IcyoNa4fFp9yL35f55_7Sqj-Xzs9w-m60st3pnykoWL0YavX9RBW6L4rCyR1nIsngqnp9K-SSfNofz9nkr5QtiqQ64O4jnAhtl3ca5a7MJ8bKyRB0et4e93K6cqtDReC8fUI8XujXfXT0v2nxLj0f2X1fdhcRz4SwlukdMNjk8fv_gWL4-0mleCwOvJtLnG53cd8PVNd_zcCalWXXRHeuU2nx1ynvoYlPdVRsdGiFPXMP4b93G8AfqJOQpQyQhTxnlvwMAAP__9-UK3g">