Skip to content

Commit ae2b303

Browse files
authored
[C++20] [Modules] Don't import initializer/pending implicit instantiations from other named module (#167468)
Close #166068 The cause of the problem is that we would import initializers and pending implicit instantiations from other named module. This is very bad and it may waste a lot of time. And we didn't observe it as the weak symbols can live together and the strong symbols would be removed by other mechanism. So we didn't observe the bad behavior for a long time. But it indeeds waste compilation time.
1 parent a7ceeff commit ae2b303

File tree

3 files changed

+65
-18
lines changed

3 files changed

+65
-18
lines changed

clang/lib/Serialization/ASTReader.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4087,10 +4087,14 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
40874087
std::errc::illegal_byte_sequence,
40884088
"Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
40894089

4090-
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
4091-
PendingInstantiations.push_back(
4092-
{ReadDeclID(F, Record, I),
4093-
ReadSourceLocation(F, Record, I).getRawEncoding()});
4090+
// For standard C++20 module, we will only reads the instantiations
4091+
// if it is the main file.
4092+
if (!F.StandardCXXModule || F.Kind == MK_MainFile) {
4093+
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
4094+
PendingInstantiations.push_back(
4095+
{ReadDeclID(F, Record, I),
4096+
ReadSourceLocation(F, Record, I).getRawEncoding()});
4097+
}
40944098
}
40954099
break;
40964100

@@ -6438,10 +6442,13 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
64386442
case SUBMODULE_INITIALIZERS: {
64396443
if (!ContextObj)
64406444
break;
6441-
SmallVector<GlobalDeclID, 16> Inits;
6442-
for (unsigned I = 0; I < Record.size(); /*in loop*/)
6443-
Inits.push_back(ReadDeclID(F, Record, I));
6444-
ContextObj->addLazyModuleInitializers(CurrentModule, Inits);
6445+
// Standard C++ module has its own way to initialize variables.
6446+
if (!F.StandardCXXModule || F.Kind == MK_MainFile) {
6447+
SmallVector<GlobalDeclID, 16> Inits;
6448+
for (unsigned I = 0; I < Record.size(); /*in loop*/)
6449+
Inits.push_back(ReadDeclID(F, Record, I));
6450+
ContextObj->addLazyModuleInitializers(CurrentModule, Inits);
6451+
}
64456452
break;
64466453
}
64476454

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3247,7 +3247,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule, ASTContext *Context) {
32473247

32483248
// Emit the reachable initializers.
32493249
// The initializer may only be unreachable in reduced BMI.
3250-
if (Context) {
3250+
if (Context && !GeneratingReducedBMI) {
32513251
RecordData Inits;
32523252
for (Decl *D : Context->getModuleInitializers(Mod))
32533253
if (wasDeclEmitted(D))
@@ -5827,17 +5827,19 @@ void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
58275827
Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES,
58285828
UnusedLocalTypedefNameCandidates);
58295829

5830-
// Write the record containing pending implicit instantiations.
5831-
RecordData PendingInstantiations;
5832-
for (const auto &I : SemaRef.PendingInstantiations) {
5833-
if (!wasDeclEmitted(I.first))
5834-
continue;
5830+
if (!GeneratingReducedBMI) {
5831+
// Write the record containing pending implicit instantiations.
5832+
RecordData PendingInstantiations;
5833+
for (const auto &I : SemaRef.PendingInstantiations) {
5834+
if (!wasDeclEmitted(I.first))
5835+
continue;
58355836

5836-
AddDeclRef(I.first, PendingInstantiations);
5837-
AddSourceLocation(I.second, PendingInstantiations);
5837+
AddDeclRef(I.first, PendingInstantiations);
5838+
AddSourceLocation(I.second, PendingInstantiations);
5839+
}
5840+
if (!PendingInstantiations.empty())
5841+
Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
58385842
}
5839-
if (!PendingInstantiations.empty())
5840-
Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
58415843

58425844
// Write the record containing declaration references of Sema.
58435845
RecordData SemaDeclRefs;

clang/test/Modules/pr166068.cppm

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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/flyweight.cppm -emit-reduced-module-interface -o %t/flyweight.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/account.cppm -emit-reduced-module-interface -o %t/account.pcm -fprebuilt-module-path=%t
7+
// RUN: %clang_cc1 -std=c++20 %t/core.cppm -emit-reduced-module-interface -o %t/core.pcm -fprebuilt-module-path=%t
8+
// RUN: %clang_cc1 -std=c++20 %t/core.cppm -fprebuilt-module-path=%t -emit-llvm -disable-llvm-passes -o - | FileCheck %t/core.cppm
9+
10+
//--- flyweight.cppm
11+
module;
12+
template <typename> struct flyweight_core {
13+
static bool init() { (void)__builtin_operator_new(2); return true; }
14+
static bool static_initializer;
15+
};
16+
template <typename T> bool flyweight_core<T>::static_initializer = init();
17+
export module flyweight;
18+
export template <class> void flyweight() {
19+
(void)flyweight_core<int>::static_initializer;
20+
}
21+
22+
//--- account.cppm
23+
export module account;
24+
import flyweight;
25+
export void account() {
26+
(void)::flyweight<int>;
27+
}
28+
29+
//--- core.cppm
30+
export module core;
31+
import account;
32+
33+
extern "C" void core() {}
34+
35+
// Fine enough to check it won't crash.
36+
// CHECK-NOT: init
37+
// CHECK-NOT: static_initializer
38+
// CHECK: define {{.*}}@core(

0 commit comments

Comments
 (0)