<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/60985>60985</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
distinct lambdas incorrectly merged across modules
</td>
</tr>
<tr>
<th>Labels</th>
<td>
bug,
c++,
c++20,
clang:modules,
miscompilation
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
zygoloid
</td>
</tr>
</table>
<pre>
If a lambda appears within a variable template, then instantiations of that lambda have the lexical context of the variable as their lexical context. This causes Clang's serialization layer to be unable to distinguish them across modules, because its approach is to number unnamed declarations within their lexical context, and two distinct lambdas from different instantiations of the variable template can end up with the same number.
Example, ready to be dropped into `test/Modules/`:
```
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: split-file %s %t
//
// RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%t/module.modulemap %t/use.cpp -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s
//--- module.modulemap
module a { header "a.h" export * }
module b { header "b.h" export * }
module c { header "c.h" export * }
//--- a.h
void not_constant();
template<typename T> struct A {
template<T M> static inline T N = [] { not_constant(); return M; } ();
};
//--- b.h
#include "a.h"
int b() { return A<int>::N<1>; }
//--- c.h
#include "a.h"
int c() { return A<int>::N<2>; }
//--- use.cpp
#include "b.h"
#include "c.h"
int bv = b();
int cv = c();
// We should not merge the two lambdas together, even though they will both
// have anonymous declaration number #1 within A<int>.
// CHECK: define {{.*}}global_var_init{{.*}} comdat($_ZN1AIiE1NILi1EEE) {
// CHECK: load i8, ptr @_ZGVN1AIiE1NILi1EEE, align 8
// CHECK: call {{.*} i32 @_ZNK1AIiE1NILi1EEMUlvE_clEv(
// CHECK: store i32 %call, ptr @_ZN1AIiE1NILi1EEE
// CHECK: define {{.*}}global_var_init{{.*}} comdat($_ZN1AIiE1NILi2EEE) {
// CHECK: load i8, ptr @_ZGVN1AIiE1NILi2EEE, align 8
// CHECK: call {{.*} i32 @_ZNK1AIiE1NILi2EEMUlvE_clEv(
// CHECK: store i32 %call, ptr @_ZN1AIiE1NILi2EEE
```
This test currently fails, because we generate calls to the `A<int>::N<1>` lambda to initialize both `A<int>::N<1>` and `A<int>::N<2>`. That happens because those two different lambdas get merged, because they're both numbered #1 within `A<int>` in the `b` and `c` module respectively.
We could perhaps fix the immediate issue by taking the context decl and mangling number into account when computing whether two lambdas should be merged, instead of numbering them inside their lexical context, at least when the context decl is a variable template specialization.
The same thing presumably happens when the variable template is at global scope instead of in a class template. That case seems especially hard to deal with, as there might be a local definition of the variable template in addition to ones from modules, and we don't have a good way to even find the lambdas that might have been instantiated locally. And the same thing presumably also happens for inline variables:
```
// header module 1
inline auto a = [] { return 1; };
```
```
// header module 2
inline auto b = [] { return 2; }
inline auto a = [] { return 1; }
```
... probably doesn't merge together the two `a` lambdas currently, and might merge the `a` from module 1 with the `b` from module 2 if we end up using lexical numbering here.
Perhaps we should address this by creating a lexical `DeclContext` corresponding to a variable, at least if we find that it's the context of a lambda. We would need this for instantiated variable template specializations and for inline variables, but having it in general seems useful.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8WF9v47gR_zT0y0CGTMV2_OCHxHHaxXWDotjrAfcSUORYYpciBZJy4vv0xVCS_8Xp3qGHAxYbSyTnH2d-8xuJEHRlEdds_sjmTxPRxdr59W-Hyhmn1aR06rD-sgMBRjSlEiDaFoUP8KZjrS0I2AuvRWkQIjatEREZ30Cs0YK2IQobtYja2QBuB7EWcRRUiz3SPjD4rqUwIJ2N-B77fXiSKwI9a3-9cQrfah1Aii5ggI0RtmJ8GSCg18Lo35JaMOKAHqKDEqGzvaEOlA5R26rToSbhDQjpXQjQONUZDORCiUky6BjIae-ErEEHOm27pkQPnbWiQQUKpRF-8HKIy02LSaywCuLbaIEcwxFg510DSu926NHGm8HDj8EGKSygVdC1SXXaFUSDg5FTlj-x_KH_f_sumtakC_Io1GEIi_KubVGBttEBW-QRQ2T8-esYi2e2yFnxcC6J3vT_-kf-zPgz_OvnF1Y8gG8g8ztgfB5vLTfflfaQtZ9uCK3RMdtpg7QlfNh36wzjc0kZ8CrlDLIQFSueJOOPjD_yHLLdcLGnX5kUssasFbFmxROpOK5ljWiT-mGB8ed-Ydr_acRgO3_uAk5l20KGjY6ZMfsGMgcZZNHr1iC83y9eF3eZ0bZ7zyrbAVtu4Fkb3NQovyf3LsKafMqyDK4V9uv9Iwhgy0eoUSj0wDgX05pxDvjeOh-B8Qdgy6eLE-XVifKHJ-TVCfn5idsekFFnC3unFVgXX6XrM5vxe8ZXrHjs14_oUWzioUWqLPjGii2E6DsZgfQNWwHONn-Dr_0uEbUEbY22CN_gBVjxBD2oJU9uqgaPsfOWRDySP3BlFLl4_H3lX3n0jxfaStMpPN3F-RFtI5S94GTJoPOBFRttIyu2VFvFwwsrNrP09PghtEel8o8olb9PKf-R0iHJbykuzxVfrMjbcdineymv4pys7Zfk9RWcF_svCKF2nUmZBA36qm8hBKgjjkZXYazRE8rhHgmKXVclYDzAmzYGShfrC7GpFQnr7KFxXTjH8xHqGS9mI7SfYji9YeLm79vNT4RICneUipS1y8cp4ymZlk-VcaUwr3vhX7XV8XoZpGuU6DP07vXXl9nDF72dvXz5h55tt9vhNm8rNE4o0Pfkdxs9sLv89de__fuDhA0IoysL97elSGHMpdGgC95Le_npQtjXn81--yrNdk_m3pQWovPYC-BzEn1h3bVtf2E0-f8dTf5nRpP_udHkp2heNer0f-JN1OVBdp7YhjnATmhzwXveECq06HuSYUxiPlRsbJF_il2LfKR30QHdSGJimEruRweJGX2yhfdbiPGJCDVxUBuOlsbaBRxI1UifRjSocMAJde4bYQHjSz8Y1hc5qosyvzRlkUPP6uh9eWaupN9Dz_QYWpRR79EcLrDhFwSZYKtFX4s2wE6_J2G6aVBpCrEOoUMoDxDFd22rtDoyYgKkpK8RtjK0OsBSYmxCStfZCG_EuaVr2o6oLT0SDF5g4wCeJZ7FhIgmCkUMs5c6aG9oRSv8H1Q2gkERBs0fDNbh1nQAFKITP59e5uXAXekCKmg9hq4RpTkcr_yo6aNcUhehBwQI0rV47loaVaQRIRxPDNkkRUAIiE0AHGxLCr1KgwIKkzIiOZwmEY_Q6KqOFEYBxlFUEjzp1DE-ZepkglL9pujAWRxI_9nQQZf8hqCcZXwZh8YElXMK3kTi66ml7TRNETQ7jU2PPOmtSmdKvJi_UPV2msMUHoajtwMtTHDHaO-cHxnV6E44DQI3R4CBMA4FMRvbe5IhOsrWa2I2MJPZSEGOjf9K_u9Qxz-qKz9Rxy8Yzx8y8JY50-kUWu_KFEPlMPT3NzCUgZEcqQpb5OIEleGEwmMK9Dd54jfjgbN0gdlp3hsh6XyZg95RKg2zYRfoosciPhU6pfNFDf5zQKi3I9USSnmkuqGuUR5AehQJYcRRHlvkTyjNZsCGRQ7SeUJDZ1WCE3cGBRfQ0Rs55LOIoGOa4c_BxJ2-PkyJAb71BBBR9Sb1WXqW6j_CnJBifDO5qUd0qYbIbE1j-NAFzYARXcBdZ6YTtS7UqliJCa5ni-WSr2bLRTGp12UhxFKJRTHPJS53C66WQq34St0td6KcryZ6zXNe5JzPc875XTFdlbyY83y-4ov8fsULdpdjI7SZ0jg5db6apN6wXuSr-_nEiBJNSJ9rOC-7ikg23xDh7qfd62een96kTyTFwxFvhveNDtQ2tEnRodfzp4lfk_qs7KrA7nKjQwwng6KOBtcfPmFom65dEp_oG8zVd5VJ5826jrFNMJJKuNKx7sqpdA3jz6Rg-JO13v0HJQ3Zyf3A-HOKwH8DAAD__-OcyFA">