[clang] [C++20] [Modules] Preserve DeductionGuideDecl if their parent are preserved (PR #222246)

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 8 23:37:24 PDT 2026


https://github.com/ChuanqiXu9 updated https://github.com/llvm/llvm-project/pull/222246

>From 7b6b119f55d8d7838c604328e3742239c768f5c4 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <chuanqi.xcq at alibaba-inc.com>
Date: Wed, 9 Sep 2026 14:04:16 +0800
Subject: [PATCH] [C++20] [Modules] Preserve DeductionGuideDecl if their parent
 are preserved

Close https://github.com/llvm/llvm-project/issues/222002

The root cause of the problem is, the deduction guide was not in the
general lookup table. The fix is to move them into the general lookup
table. This should be fine as the DeductionGuide may not pollute the
name lookup results.
---
 clang/lib/Serialization/ASTWriter.cpp | 13 +++++--
 clang/test/Modules/pr222002.cppm      | 53 +++++++++++++++++++++++++++
 2 files changed, 62 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/Modules/pr222002.cppm

diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index de985b770cb01..944e68ea6481d 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4317,11 +4317,16 @@ static bool isModuleLocalDecl(NamedDecl *D) {
       Parent && !D->getNonTransparentDeclContext()->isFileContext())
     return isModuleLocalDecl(Parent);
 
-  // Deduction Guide are special here. Since their logical parent context are
-  // not their actual parent.
+  // Deduction guides are not found by name lookup. Keep them in the general
+  // lookup table so that Sema can consider all reachable deduction guides,
+  // including when instantiating an exported template that uses a
+  // non-exported class template.
+  if (isa<CXXDeductionGuideDecl>(D))
+    return false;
+
   if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
-    if (auto *CDGD = dyn_cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()))
-      return isModuleLocalDecl(CDGD->getDeducedTemplate());
+    if (isa<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()))
+      return false;
 
   if (D->getFormalLinkage() != Linkage::Module)
     return false;
diff --git a/clang/test/Modules/pr222002.cppm b/clang/test/Modules/pr222002.cppm
new file mode 100644
index 0000000000000..3c9959440480c
--- /dev/null
+++ b/clang/test/Modules/pr222002.cppm
@@ -0,0 +1,53 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/mod.cppm -emit-module-interface -o %t/mod.pcm
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fmodule-file=mod=%t/mod.pcm \
+// RUN:   -fsyntax-only -verify
+//
+// Test  again with reduced BMI
+// RUN: %clang_cc1 -std=c++20 %t/mod.cppm -emit-reduced-module-interface \
+// RUN:   -o %t/mod.pcm
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fmodule-file=mod=%t/mod.pcm \
+// RUN:   -fsyntax-only -verify
+
+//--- mod.cppm
+export module mod;
+
+export template <typename T> struct dependent {
+  dependent(int) {}
+};
+
+template <typename U> dependent(U) -> dependent<U>;
+
+export template <typename T> struct independent {
+  independent(int) {}
+};
+
+independent(int) -> independent<int>;
+
+export template <int N> struct nontype {
+  nontype(int) {}
+};
+
+nontype(int) -> nontype<1>;
+
+template <typename T> struct wrapped {
+  wrapped(int) {}
+};
+
+template <typename U> wrapped(U) -> wrapped<U>;
+
+export template <bool> void use_it() { wrapped d(1); }
+
+//--- use.cpp
+// expected-no-diagnostics
+import mod;
+
+void use() {
+  dependent d(1);
+  independent i(1);
+  nontype n(1);
+  use_it<true>();
+}



More information about the cfe-commits mailing list