Skip to content

Commit a68638b

Browse files
committed
[C++20] [Modules] [Reduced BMI] Handling Deduction Guide in reduced BMI
carefully Close #93859 The direct pattern of the issue is that, in a reduced BMI, we're going to wrtie a class but we didn't write the deduction guide. Although we handled deduction guide, but we tried to record the found deduction guide from `noload_lookup` directly. It is slightly problematic if the found deduction guide is from AST. e.g., ``` module; export module m; import xxx; // Also contains the class and the deduction guide ... ``` Then when we writes the class in the current file, we tried to record the deduction guide, but `noload_lookup` returns the deduction guide from the AST file then we didn't record the local deduction guide. Then mismatch happens. To mitiagte the problem, we tried to record the canonical declaration for the decution guide.
1 parent 5161a3f commit a68638b

File tree

2 files changed

+147
-1
lines changed

2 files changed

+147
-1
lines changed

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1733,7 +1733,7 @@ void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
17331733
if (Writer.isGeneratingReducedBMI()) {
17341734
auto Name = Context.DeclarationNames.getCXXDeductionGuideName(D);
17351735
for (auto *DG : D->getDeclContext()->noload_lookup(Name))
1736-
Writer.GetDeclRef(DG);
1736+
Writer.GetDeclRef(DG->getCanonicalDecl());
17371737
}
17381738

17391739
Code = serialization::DECL_CLASS_TEMPLATE;

clang/test/Modules/pr93859.cppm

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Reduced from https://github.com/llvm/llvm-project/issues/93859
2+
//
3+
// RUN: rm -rf %t
4+
// RUN: mkdir -p %t
5+
// RUN: split-file %s %t
6+
//
7+
// RUN: %clang_cc1 -std=c++20 %t/reduced_std.cppm -emit-reduced-module-interface -o %t/reduced_std.pcm
8+
// RUN: %clang_cc1 -std=c++20 %t/Misc.cppm -emit-reduced-module-interface -o %t/Misc.pcm \
9+
// RUN: -fprebuilt-module-path=%t
10+
// RUN: %clang_cc1 -std=c++20 %t/Instance.cppm -emit-reduced-module-interface -o %t/Instance.pcm \
11+
// RUN: -fprebuilt-module-path=%t
12+
// RUN: %clang_cc1 -std=c++20 %t/Device.cppm -emit-reduced-module-interface -o %t/Device.pcm \
13+
// RUN: -fprebuilt-module-path=%t
14+
// RUN: %clang_cc1 -std=c++20 %t/Overlay.cppm -emit-reduced-module-interface -o %t/Overlay.pcm \
15+
// RUN: -fprebuilt-module-path=%t
16+
// RUN: %clang_cc1 -std=c++20 %t/App.cppm -emit-module-interface -o /dev/null \
17+
// RUN: -fexperimental-modules-reduced-bmi -fmodule-output=%t/App.pcm \
18+
// RUN: -fprebuilt-module-path=%t
19+
// RUN: %clang_cc1 -std=c++20 %t/test.cc -fsyntax-only -verify \
20+
// RUN: -fprebuilt-module-path=%t
21+
22+
//--- header.h
23+
namespace std {
24+
25+
template <class _T1, class _T2>
26+
struct pair
27+
{
28+
_T1 first;
29+
_T2 second;
30+
31+
constexpr pair()
32+
: first(), second() {}
33+
34+
constexpr pair(_T1 const& __t1, _T2 const& __t2)
35+
: first(__t1), second(__t2) {}
36+
};
37+
38+
template <class _T1, class _T2>
39+
pair(_T1, _T2) -> pair<_T1, _T2>;
40+
41+
template <class _Tp>
42+
class __tree_const_iterator {
43+
public:
44+
template <class>
45+
friend class __tree;
46+
};
47+
48+
template <class _Tp>
49+
class __tree {
50+
public:
51+
typedef _Tp value_type;
52+
typedef __tree_const_iterator<value_type> const_iterator;
53+
54+
template <class, class, class, class>
55+
friend class map;
56+
};
57+
58+
template <class _Key>
59+
class set {
60+
public:
61+
typedef __tree<_Key> __base;
62+
63+
typedef typename __base::const_iterator iterator;
64+
65+
set() {}
66+
67+
pair<iterator, bool>
68+
insert(const _Key& __v);
69+
};
70+
71+
template <class _InputIterator, class _OutputIterator>
72+
inline constexpr _OutputIterator
73+
copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
74+
return pair{__first, __last}.second;
75+
}
76+
77+
}
78+
79+
//--- reduced_std.cppm
80+
module;
81+
#include "header.h"
82+
export module reduced_std;
83+
84+
export namespace std {
85+
using std::set;
86+
using std::copy;
87+
}
88+
89+
//--- Misc.cppm
90+
export module Misc;
91+
import reduced_std;
92+
93+
export void check_result(int res) {
94+
std::set<char> extensions;
95+
extensions.insert('f');
96+
}
97+
98+
//--- Instance.cppm
99+
export module Instance;
100+
import reduced_std;
101+
102+
export class Instance {
103+
public:
104+
Instance() {
105+
std::set<const char*> extensions;
106+
extensions.insert("foo");
107+
}
108+
};
109+
110+
//--- Device.cppm
111+
export module Device;
112+
import reduced_std;
113+
import Instance;
114+
import Misc;
115+
116+
std::set<int> wtf_set;
117+
118+
//--- Overlay.cppm
119+
export module Overlay;
120+
121+
import reduced_std;
122+
import Device;
123+
124+
void overlay_vector_use() {
125+
std::set<int> nums;
126+
nums.insert(1);
127+
}
128+
129+
//--- App.cppm
130+
module;
131+
#include "header.h"
132+
export module App;
133+
import Overlay;
134+
135+
std::set<float> fs;
136+
137+
//--- test.cc
138+
// expected-no-diagnostics
139+
import reduced_std;
140+
import App;
141+
142+
void render() {
143+
unsigned *oidxs = nullptr;
144+
unsigned idxs[] = {0, 1, 2, 0, 2, 3};
145+
std::copy(idxs, idxs + 6, oidxs);
146+
}

0 commit comments

Comments
 (0)