Skip to content

Commit

Permalink
[C++20] [Modules] Emit implicit Deduction Guide for implicit class sp…
Browse files Browse the repository at this point in the history
…ecialization

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.
  • Loading branch information
ChuanqiXu9 committed Sep 29, 2024
1 parent a522516 commit bf9ab0b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
12 changes: 12 additions & 0 deletions clang/lib/Serialization/ASTWriterDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
45 changes: 45 additions & 0 deletions clang/test/Modules/lambda-definitions.cppm
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit bf9ab0b

Please sign in to comment.