Skip to content

Commit 3f0cf74

Browse files
committed
[C++20] [Modules] [Reduced BMI] Don't write specializations with local args
Close #119947 As discussed in the above thread, we shouldn't write specializations with local args in reduced BMI. Since users can't find such specializations any way.
1 parent 9d491bc commit 3f0cf74

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,48 @@ namespace clang {
221221
Record.AddDeclRef(F.second);
222222
}
223223

224+
template <typename T> bool shouldSkipWritingSpecializations(T *Spec) {
225+
// Now we will only avoid writing specializations if we're generating
226+
// reduced BMI.
227+
if (!GeneratingReducedBMI)
228+
return false;
229+
230+
assert((isa<FunctionDecl, ClassTemplateSpecializationDecl,
231+
VarTemplateSpecializationDecl>(Spec)));
232+
233+
ArrayRef<TemplateArgument> Args;
234+
if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Spec))
235+
Args = CTSD->getTemplateArgs().asArray();
236+
else if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Spec))
237+
Args = VTSD->getTemplateArgs().asArray();
238+
else
239+
Args = cast<FunctionDecl>(Spec)
240+
->getTemplateSpecializationArgs()
241+
->asArray();
242+
243+
// If there is any template argument is TULocal, we can avoid writing the
244+
// specialization since the consumers of reduced BMI won't get the
245+
// specialization anyway.
246+
for (const TemplateArgument &TA : Args) {
247+
switch (TA.getKind()) {
248+
case TemplateArgument::Type: {
249+
Linkage L = TA.getAsType()->getLinkage();
250+
if (!isExternallyVisible(L))
251+
return true;
252+
break;
253+
}
254+
case TemplateArgument::Declaration:
255+
if (!TA.getAsDecl()->isExternallyVisible())
256+
return true;
257+
break;
258+
default:
259+
break;
260+
}
261+
}
262+
263+
return false;
264+
}
265+
224266
/// Add to the record the first template specialization from each module
225267
/// file that provides a declaration of D. We store the DeclId and an
226268
/// ODRHash of the template arguments of D which should provide enough
@@ -235,6 +277,9 @@ namespace clang {
235277
CollectFirstDeclFromEachModule(D, /*IncludeLocal*/ true, Firsts);
236278

237279
for (const auto &F : Firsts) {
280+
if (shouldSkipWritingSpecializations(F.second))
281+
continue;
282+
238283
if (isa<ClassTemplatePartialSpecializationDecl,
239284
VarTemplatePartialSpecializationDecl>(F.second))
240285
PartialSpecsInMap.push_back(F.second);

clang/test/Modules/pr119947.cppm

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t -emit-llvm -o -
7+
8+
9+
//--- a.cppm
10+
export module a;
11+
12+
struct a_inner {
13+
~a_inner() {
14+
}
15+
void f(auto) {
16+
}
17+
};
18+
19+
export template<typename T>
20+
struct a {
21+
a() {
22+
struct local {};
23+
inner.f(local());
24+
}
25+
private:
26+
a_inner inner;
27+
};
28+
29+
30+
namespace {
31+
32+
struct s {
33+
};
34+
35+
} // namespace
36+
37+
void f() {
38+
a<s> x;
39+
}
40+
41+
//--- use.cpp
42+
import a;
43+
44+
namespace {
45+
46+
struct s {
47+
};
48+
49+
} // namespace
50+
51+
void g() {
52+
a<s> x;
53+
}
54+

0 commit comments

Comments
 (0)