[clang] bf9ab0b - [C++20] [Modules] Emit implicit Deduction Guide for implicit class specialization

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 28 19:41:05 PDT 2024


Author: Chuanqi Xu
Date: 2024-09-29T10:38:05+08:00
New Revision: bf9ab0b7c3ba1d4a89a3dd9b00909ad3cfab3d48

URL: https://github.com/llvm/llvm-project/commit/bf9ab0b7c3ba1d4a89a3dd9b00909ad3cfab3d48
DIFF: https://github.com/llvm/llvm-project/commit/bf9ab0b7c3ba1d4a89a3dd9b00909ad3cfab3d48.diff

LOG: [C++20] [Modules] Emit implicit Deduction Guide for implicit class specialization

Fixed a crash for the attached test case due to we missed to emit the
deduction guide. The reason is, the deduction guide is attached to the
export-decl in the imported module. So we won't emit it by traversing the
AST of the current TU.

Added: 
    clang/test/Modules/lambda-definitions.cppm

Modified: 
    clang/lib/Serialization/ASTWriterDecl.cpp

Removed: 
    


################################################################################
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 <class _Fn, class... _Args>
+concept invocable = requires(_Fn&& __fn, _Args&&... __args) {
+  _Fn(__args...);
+};
+
+export template <class _Fn, class _Args>
+constexpr bool is_callable(_Fn&& __fn, _Args&& __args) {
+    return invocable<_Fn, _Args>;
+}
+
+export template <class _Fn>
+struct Callable : _Fn {
+    constexpr explicit Callable(_Fn &&__fn) : _Fn(static_cast<_Fn&&>(__fn)) {}
+    
+    template <class _Args>
+    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);


        


More information about the cfe-commits mailing list