diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index b9222a1b33fd74..b71684569609ac 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1785,6 +1785,18 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( if (ArgsWritten) Record.AddASTTemplateArgumentListInfo(ArgsWritten); + // Mention the implicitly generated C++ deduction guide to make sure the + // deduction guide will be rewritten as expected. + // + // FIXME: Would it be more efficient to add a callback register function + // in sema to register the deduction guide? + if (Writer.isWritingStdCXXNamedModules()) { + auto Name = Context.DeclarationNames.getCXXDeductionGuideName( + D->getSpecializedTemplate()); + for (auto *DG : D->getDeclContext()->noload_lookup(Name)) + Writer.GetDeclRef(DG->getCanonicalDecl()); + } + Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION; } diff --git a/clang/test/Modules/lambda-definitions.cppm b/clang/test/Modules/lambda-definitions.cppm new file mode 100644 index 00000000000000..fb4bb8d298f0f0 --- /dev/null +++ b/clang/test/Modules/lambda-definitions.cppm @@ -0,0 +1,45 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/invocable.cppm -emit-module-interface -o %t/invocable.pcm +// RUN: %clang_cc1 -std=c++20 %t/lambda.cppm -emit-module-interface -o %t/lambda.pcm -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -verify +// +// RUN: %clang_cc1 -std=c++20 %t/invocable.cppm -emit-reduced-module-interface -o %t/invocable.pcm +// RUN: %clang_cc1 -std=c++20 %t/lambda.cppm -emit-reduced-module-interface -o %t/lambda.pcm -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/test.cc -fprebuilt-module-path=%t -fsyntax-only -verify + +//--- invocable.cppm +export module invocable; +export template +concept invocable = requires(_Fn&& __fn, _Args&&... __args) { + _Fn(__args...); +}; + +export template +constexpr bool is_callable(_Fn&& __fn, _Args&& __args) { + return invocable<_Fn, _Args>; +} + +export template +struct Callable : _Fn { + constexpr explicit Callable(_Fn &&__fn) : _Fn(static_cast<_Fn&&>(__fn)) {} + + template + constexpr auto operator()(_Args&& __args) { + return _Fn(__args); + } +}; + +//--- lambda.cppm +export module lambda; +import invocable; +export constexpr auto l = Callable([](auto &&x){}); + +//--- test.cc +// expected-no-diagnostics +import invocable; +import lambda; + +static_assert(is_callable(l, 4) == true);