Skip to content

Commit abdcef3

Browse files
committed
WIP: Serialize pending constexr instantiations
I wanted to avoid loading eagerly all function templates and their instantiations - even if ultimately `PendingInstantiations` - which contains the same information is going to be loaded at the end of the TU. So instead, when we find the definition of a constexpr function template we load the associated instantiation from the external modules at that point. I'm not sure there is a better way to get to a DeclID from a Decl* than to iterate over all redeclarations? I still need to cleanup but I'd like feedback on direction first!
1 parent af4176f commit abdcef3

File tree

9 files changed

+96
-6
lines changed

9 files changed

+96
-6
lines changed

clang/include/clang/Sema/ExternalSemaSource.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ class ExternalSemaSource : public ExternalASTSource {
181181
SmallVectorImpl<std::pair<ValueDecl *,
182182
SourceLocation> > &Pending) {}
183183

184+
virtual void ReadPendingOfInstantiationsForConstexprEntity(
185+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls){};
186+
184187
/// Read the set of late parsed template functions for this source.
185188
///
186189
/// The external source should insert its own late parsed template functions

clang/include/clang/Sema/MultiplexExternalSemaSource.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,9 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
319319
void ReadPendingInstantiations(
320320
SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending) override;
321321

322+
virtual void ReadPendingOfInstantiationsForConstexprEntity(
323+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls) override;
324+
322325
/// Read the set of late parsed template functions for this source.
323326
///
324327
/// The external source should insert its own late parsed template functions

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,10 @@ enum ASTRecordTypes {
695695
/// Record code for an unterminated \#pragma clang assume_nonnull begin
696696
/// recorded in a preamble.
697697
PP_ASSUME_NONNULL_LOC = 67,
698+
699+
/// Record code for constexpr templated entities that have been used but not
700+
/// yet instantiated.
701+
PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES = 68,
698702
};
699703

700704
/// Record types used within a source manager block.

clang/include/clang/Serialization/ASTReader.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,9 @@ class ASTReader
814814
/// is the instantiation location.
815815
SmallVector<serialization::DeclID, 64> PendingInstantiations;
816816

817+
llvm::DenseMap<serialization::DeclID, std::set<serialization::DeclID>>
818+
PendingInstantiationsOfConstexprEntities;
819+
817820
//@}
818821

819822
/// \name DiagnosticsEngine-relevant special data
@@ -2101,6 +2104,9 @@ class ASTReader
21012104
SmallVectorImpl<std::pair<ValueDecl *,
21022105
SourceLocation>> &Pending) override;
21032106

2107+
virtual void ReadPendingOfInstantiationsForConstexprEntity(
2108+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls) override;
2109+
21042110
void ReadLateParsedTemplates(
21052111
llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
21062112
&LPTMap) override;

clang/lib/Sema/MultiplexExternalSemaSource.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,12 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations(
310310
Sources[i]->ReadPendingInstantiations(Pending);
311311
}
312312

313+
void MultiplexExternalSemaSource::ReadPendingOfInstantiationsForConstexprEntity(
314+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls) {
315+
for (size_t i = 0; i < Sources.size(); ++i)
316+
Sources[i]->ReadPendingOfInstantiationsForConstexprEntity(D, Decls);
317+
};
318+
313319
void MultiplexExternalSemaSource::ReadLateParsedTemplates(
314320
llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
315321
&LPTMap) {

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6501,15 +6501,25 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
65016501
// see CWG2497.
65026502
void Sema::InstantiateFunctionTemplateSpecializations(
65036503
SourceLocation PointOfInstantiation, FunctionDecl *Tpl) {
6504+
6505+
auto InstantiateAll = [&](const auto &Range) {
6506+
for (NamedDecl *Fun : Range) {
6507+
InstantiateFunctionDefinition(PointOfInstantiation,
6508+
cast<FunctionDecl>(Fun));
6509+
}
6510+
};
6511+
65046512
auto It =
65056513
PendingInstantiationsOfConstexprEntities.find(Tpl->getCanonicalDecl());
6506-
if (It == PendingInstantiationsOfConstexprEntities.end())
6507-
return;
6508-
for (NamedDecl *Fun : It->second) {
6509-
InstantiateFunctionDefinition(PointOfInstantiation,
6510-
cast<FunctionDecl>(Fun));
6514+
if (It != PendingInstantiationsOfConstexprEntities.end()) {
6515+
InstantiateAll(It->second);
6516+
}
6517+
6518+
llvm::SmallSetVector<NamedDecl *, 4> Decls;
6519+
if (ExternalSource) {
6520+
ExternalSource->ReadPendingOfInstantiationsForConstexprEntity(Tpl, Decls);
6521+
InstantiateAll(Decls);
65116522
}
6512-
PendingInstantiationsOfConstexprEntities.erase(It);
65136523
}
65146524

65156525
void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,

clang/lib/Serialization/ASTReader.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3709,6 +3709,19 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
37093709
}
37103710
break;
37113711

3712+
case PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES:
3713+
if (Record.size() % 2 != 0)
3714+
return llvm::createStringError(
3715+
std::errc::illegal_byte_sequence,
3716+
"Invalid PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES block");
3717+
3718+
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
3719+
DeclID Key = getGlobalDeclID(F, Record[I++]);
3720+
DeclID Value = getGlobalDeclID(F, Record[I++]);
3721+
PendingInstantiationsOfConstexprEntities[Key].insert(Value);
3722+
}
3723+
break;
3724+
37123725
case SEMA_DECL_REFS:
37133726
if (Record.size() != 3)
37143727
return llvm::createStringError(std::errc::illegal_byte_sequence,
@@ -8718,6 +8731,18 @@ void ASTReader::ReadPendingInstantiations(
87188731
PendingInstantiations.clear();
87198732
}
87208733

8734+
void ASTReader::ReadPendingOfInstantiationsForConstexprEntity(
8735+
const NamedDecl *D, llvm::SmallSetVector<NamedDecl *, 4> &Decls) {
8736+
for (auto *Redecl : D->redecls()) {
8737+
DeclID Id = Redecl->getGlobalID();
8738+
auto It = PendingInstantiationsOfConstexprEntities.find(Id);
8739+
if (It == PendingInstantiationsOfConstexprEntities.end())
8740+
continue;
8741+
for (DeclID InstantiationId : It->second)
8742+
Decls.insert(cast<NamedDecl>(GetDecl(InstantiationId)));
8743+
}
8744+
}
8745+
87218746
void ASTReader::ReadLateParsedTemplates(
87228747
llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
87238748
&LPTMap) {

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,7 @@ void ASTWriter::WriteBlockInfoBlock() {
849849
RECORD(SEMA_DECL_REFS);
850850
RECORD(WEAK_UNDECLARED_IDENTIFIERS);
851851
RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
852+
RECORD(PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES);
852853
RECORD(UPDATE_VISIBLE);
853854
RECORD(DECL_UPDATE_OFFSETS);
854855
RECORD(DECL_UPDATES);
@@ -4836,6 +4837,16 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
48364837
assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
48374838
"There are local ones at end of translation unit!");
48384839

4840+
// Build a record containing all of pending instantiations of constexpr
4841+
// entities.
4842+
RecordData PendingInstantiationsOfConstexprEntities;
4843+
for (const auto &I : SemaRef.PendingInstantiationsOfConstexprEntities) {
4844+
for (const auto &Elem : I.second) {
4845+
AddDeclRef(I.first, PendingInstantiationsOfConstexprEntities);
4846+
AddDeclRef(Elem, PendingInstantiationsOfConstexprEntities);
4847+
}
4848+
}
4849+
48394850
// Build a record containing some declaration references.
48404851
RecordData SemaDeclRefs;
48414852
if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) {
@@ -5153,6 +5164,11 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
51535164
if (!PendingInstantiations.empty())
51545165
Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
51555166

5167+
// Write the record containing pending instantiations of constexpr entities.
5168+
if (!PendingInstantiationsOfConstexprEntities.empty())
5169+
Stream.EmitRecord(PENDING_INSTANTIATIONS_OF_CONSTEXPR_ENTITIES,
5170+
PendingInstantiationsOfConstexprEntities);
5171+
51565172
// Write the record containing declaration references of Sema.
51575173
if (!SemaDeclRefs.empty())
51585174
Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t
2+
// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s
3+
4+
// expected-no-diagnostics
5+
6+
#ifndef HEADER
7+
#define HEADER
8+
9+
template<typename T> constexpr T f();
10+
constexpr int g() { return f<int>(); } // #1
11+
12+
#else /*included pch*/
13+
14+
template<typename T> constexpr T f() { return 123; }
15+
int k[g()];
16+
17+
#endif // HEADER

0 commit comments

Comments
 (0)