
This is a fix for the following issue: when a lambda’s class type is merged across modules (e.g. because it is defined in a template in the GMF of some module `A`, and some other module `B` both imports `A` and has the same template in its GMF), then `getLambdaCallOperator()` might return the wrong operator (e.g. while compiling `B`, the lambda’s class type would be the one attached to `B`’s GMF, but the call operator ends up being the one attached to `A`’s GMF). This causes issues in situations where the call operator is in a template and accesses declarations in the surrounding context: when those declarations are instantated, a mapping is introduced from the original node in the template to that of the instantiation. If such an instantiation happens in `B`, and we then try to instantiate `A`’s call operator, any nodes in that call operator refer to declarations in the template in `A`, but the `LocalInstantiationScope` only contains mappings for declarations in `B`! This causes the following assertion (for godbolt links and more, see the issue below): ``` Assertion `isa<LabelDecl>(D) && "declaration not instantiated in this scope"' failed. ``` We now walk the redecl chain of the call operator to find the one that is in the same module as the record decl. This fixes #110401.
45 lines
992 B
C++
45 lines
992 B
C++
// RUN: rm -rf %t
|
|
// RUN: mkdir %t
|
|
// RUN: split-file %s %t
|
|
//
|
|
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux -emit-module-interface %t/a.cppm -o %t/A.pcm
|
|
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux -emit-module-interface -fprebuilt-module-path=%t %t/b.cppm -o %t/B.pcm
|
|
|
|
// Just check that this doesn't crash.
|
|
|
|
//--- a.cppm
|
|
module;
|
|
|
|
template <typename _Visitor>
|
|
void __do_visit(_Visitor &&__visitor) {
|
|
using _V0 = int;
|
|
[](_V0 __v) -> _V0 { return __v; } (1);
|
|
}
|
|
|
|
export module A;
|
|
|
|
void g() {
|
|
struct Visitor { };
|
|
__do_visit(Visitor());
|
|
}
|
|
|
|
//--- b.cppm
|
|
module;
|
|
|
|
template <typename _Visitor>
|
|
void __do_visit(_Visitor &&__visitor) {
|
|
using _V0 = int;
|
|
|
|
// Check that we instantiate this lambda's call operator in 'f' below
|
|
// instead of the one in 'a.cppm' here; otherwise, we won't find a
|
|
// corresponding instantiation of the using declaration above.
|
|
[](_V0 __v) -> _V0 { return __v; } (1);
|
|
}
|
|
|
|
export module B;
|
|
import A;
|
|
|
|
void f() {
|
|
__do_visit(1);
|
|
}
|