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

    <tr>
        <th>Summary</th>
        <td>
            USRGenerator doesn't handle lambda expressions as arguments in template specializations
        </td>
    </tr>

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

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

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

<pre>
    Currently, `USRGenerator` doesn't handle template specializations/instantiations, which contain lambda expression as one of their arguments, resulting in the USR for such instantiation to be the same as the USR for the template declaration. I created a `c-index-test` test case to visualize this issue:

`template_instantiation_lambda_arguments.cpp`:
```cpp
// RUN: c-index-test core -print-source-symbols -- %s | FileCheck %s

template <typename F> int a(F &&f) { return f(42); }
// CHECK: {{[0-9]+}}:27 | function/C | a | c:@FT@>1#Ta#&&t0.0#I# |
// OK

template <typename T> struct A {
    A(T t) : op{t} {}

    T op;
};
// CHECK: {{[0-9]+}}:30 | struct(Gen)/C++ | A | c:@ST>1#T@A
// OK

int foo()
{
    auto v = a([](auto &&arg) { return arg*2; });
    // CHECK: {{[0-9]+}}:14 | function/C | a | c:@FT@>1#Ta#&&t0.0#I# |
    // BAD - instantiation of a<F>(F &&f) with a lambda has the same USR as the a<F>(F &&f)
    // template declaration

    auto v2 = a([](auto &&arg) { return arg+2; });
 // CHECK: {{[0-9]+}}:15 | function/C | a | c:@FT@>1#Ta#&&t0.0#I# |
    // BAD - instantiation of a<F>(F &&f) has the same USR as the a<F>(F &&f) template declaration
    //       and previous instantiation with different lambda

    auto sub = [](auto &&arg) { return arg-2; };
    auto callable = A<decltype(sub)>(sub);
    // CHECK: {{[0-9]+}}:21 | struct(Gen)/C++ | A | c:@ST>1#T@A |
    // BAD - above instantiation of A<T> has the same exact USR as A<T> declaration

    return v+v2+callable.op(24);
}
```
The test case passes, however note the identical USR strings for different instantiations. It can be executed on the LLVM build as follows:

```bash
build/bin/c-index-test core -print-source-symbols -- clang/test/Index/USR/template_instantiation_lambda_arguments.cpp | build/bin/FileCheck clang/test/Index/USR/template_instantiation_lambda_arguments.cpp
```

An easy fix would be to add an `if` case to `CXXRecordDecl` handling in [USRGenerator::VisitTagDecl](https://github.com/llvm/llvm-project/blob/release/21.x/clang/lib/Index/USRGeneration.cpp#L524), for a lambda it would be enough to just add some new prefix and source location, as it's the only unique way to represent a lambda type.

This issue is related to my previous issue on USRGenerator: #155082
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzMV11z4jgW_TWXl1tQRsZgHngwEM-mpne3KiFT89Yl2xfQjJBYSSZhfv3WlYFA0tnq9PbDpFwBZH3cc879kvRebQzRDLI5ZMuebMPWuln1pzv-JXuVbY6zRescmaCPIBYI4-Tp8eEXMuRksA7GCTaWvAExCbiVptGEgXZ7LQOh31OtpFZ_yaCs8SBKZXyQJqjzwAKft6reYm1NkMqglruqkUgve0feK2tQerSG0K4xbEk5lG7T7siEuNiRb3VQZoPK8Ht8enzAtXXo23qLN4dhsFhRnOTljnjf6wX8_WJ3Q7WWLi4b4D3WjmSgBiWjr_vKNPTSD-QDo-dPrKUnPuCgfMt4-RzlUXnfEqQFJPEZJ-cTvt6Y9rVD_fUCbVDv9zBOTivHSffwYFKAKEGU-PD0L0gLvLYGa-sI-3unTOh727qa-v64q6z22O8jiMwjTBZYKk2LLdV_xqHOtgt0SBfhuCfDFJWQ3qEyASWIvEQQYxDjNYgpwmSOjkLrDK5B5CMBYgrpHGGyfDVx8Y-7xa9sJEzm_GTzpD-FbAlizvMmS0gLMYkmrVtTMxMgykUckPF_zQyMknIFowTSuyGIdCVBpJ0lIRkkINJ7ECnPfj3437_-D1ArBuWDa-uAnWlJgYhYgMhXGCK6tEC7h8k8wGTZWb_sduSJK36X8rIIYf45wGkSkXUGgMh_IcPciXLBs8Q8vi2u0T-uztBh1PnRLUoWaG0tiJw3YqvOkGTLLomQLqOCXYSDyON4x6F0mzd6xpFCnNWMup72-wTM4ehn6np1-LxYYv9NZNs1SkgX7K5vHfVZhS3Kc1rZnoI-JgCO_NPvD1bfnvyt7PDqFR3X4kfInr8n-zNMZ38Ppj_J7Ud0XhnQ_UnT4N7RQdnWv7Emituo9Zq4Pp1EfiOJb6uoyXfr0b-okd7EUS21lpWmuFsB6YLt5qwCIvdtFbW7u_r-A0Ejhv9fbvhIQ1nZA71XkkHEbHgjHb3IOpwFvEz5ps-fSDuAmB8EiPmZooHdg8jF6MLDKX-eCxkkxSqW23Pl3EvvKRb0rX2mAzk0NnS1WjVkgqqljib54JTZ-FixX4W_bSoGeM_bGq729EJ1y6Xbdu3Bly-__ROrVumG0a2t1vbZXxfo7qmk30JSxIkgykpxWH2i1NZamg2IMvYIorzndSDKp8eHOPjdPUCU-taK1-L9sw55owwkRWGQpD_iWr3gs211Exsni7JpUBpugtSaW59z1wPjZPH77w9UW9csqdb8LraCp8YMsvlNz5gWkBa_Ka_CSm7ighiZ2xD2UYzouxsVtm01qO0ORKn14fzR3zv7B3F8lJW2FYjSkSbpCUQphgOm4MyMVtUtMScTuK1j4CL9knVeKhbRpS6FQoVX4GRsu9kyzj9aHyIJ3u4IDT1zYmKSOEd1XoDa1l2UiAW7mAogJl10WaOP2Br1n5bwWR55Q0fc5rILX07mjDLoZFhdWkhUHh3p2IQGi7vjVUaM763BNwwjiHSYZUkues0sbabpVPZoNpxkk2Sa5emot52NkyQfZ3kzGo3z9WQ4rsb5dJjTMJk02XCYZT01E4nIkmmSDfNhko4GTTOcjsdVIxshRSIbGCW0k0oPWJiBdZteNGc2zCa8XsuKtI83CyGYrq4fFoIvGm4W1azajYdRopUP_nWboIKm2TWk97eMd1cFz4RfXDveCD64iPRap2efdrdoPV9iTvAOM_HfAAAA__9xV_SQ">