aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Frontend/PCHReader.cpp19
-rw-r--r--lib/Frontend/PCHWriter.cpp16
-rw-r--r--lib/Sema/Sema.cpp43
3 files changed, 58 insertions, 20 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 7229775070..98b274d175 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1739,6 +1739,15 @@ PCHReader::ReadPCHBlock(PerFileData &F) {
DynamicClasses.swap(Record);
break;
+ case pch::PENDING_IMPLICIT_INSTANTIATIONS:
+ // Optimization for the first block.
+ if (PendingImplicitInstantiations.empty())
+ PendingImplicitInstantiations.swap(Record);
+ else
+ PendingImplicitInstantiations.insert(
+ PendingImplicitInstantiations.end(), Record.begin(), Record.end());
+ break;
+
case pch::SEMA_DECL_REFS:
if (!SemaDeclRefs.empty()) {
Error("duplicate SEMA_DECL_REFS record in PCH file");
@@ -3191,6 +3200,16 @@ void PCHReader::InitializeSema(Sema &S) {
SemaObj->DynamicClasses.push_back(
cast<CXXRecordDecl>(GetDecl(DynamicClasses[I])));
+ // If there were any pending implicit instantiations, deserialize them
+ // and add them to Sema's queue of such instantiations.
+ assert(PendingImplicitInstantiations.size() % 2 == 0 &&
+ "Expected pairs of entries");
+ for (unsigned Idx = 0, N = PendingImplicitInstantiations.size(); Idx < N;) {
+ ValueDecl *D=cast<ValueDecl>(GetDecl(PendingImplicitInstantiations[Idx++]));
+ SourceLocation Loc = ReadSourceLocation(PendingImplicitInstantiations, Idx);
+ SemaObj->PendingImplicitInstantiations.push_back(std::make_pair(D, Loc));
+ }
+
// Load the offsets of the declarations that Sema references.
// They will be lazily deserialized when needed.
if (!SemaDeclRefs.empty()) {
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index d6dc36fd30..86b2273ea6 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -2255,6 +2255,17 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I)
AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses);
+ // Build a record containing all of pending implicit instantiations.
+ RecordData PendingImplicitInstantiations;
+ for (std::deque<Sema::PendingImplicitInstantiation>::iterator
+ I = SemaRef.PendingImplicitInstantiations.begin(),
+ N = SemaRef.PendingImplicitInstantiations.end(); I != N; ++I) {
+ AddDeclRef(I->first, PendingImplicitInstantiations);
+ AddSourceLocation(I->second, PendingImplicitInstantiations);
+ }
+ assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
+ "There are local ones at end of translation unit!");
+
// Build a record containing some declaration references.
RecordData SemaDeclRefs;
if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
@@ -2347,6 +2358,11 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
if (!DynamicClasses.empty())
Stream.EmitRecord(pch::DYNAMIC_CLASSES, DynamicClasses);
+ // Write the record containing pending implicit instantiations.
+ if (!PendingImplicitInstantiations.empty())
+ Stream.EmitRecord(pch::PENDING_IMPLICIT_INSTANTIATIONS,
+ PendingImplicitInstantiations);
+
// Write the record containing declaration references of Sema.
if (!SemaDeclRefs.empty())
Stream.EmitRecord(pch::SEMA_DECL_REFS, SemaDeclRefs);
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 6de4202bae..244538147e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -215,26 +215,29 @@ void Sema::DeleteStmt(StmtTy *S) {
/// ActOnEndOfTranslationUnit - This is called at the very end of the
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
-void Sema::ActOnEndOfTranslationUnit() {
- while (1) {
- // C++: Perform implicit template instantiations.
- //
- // FIXME: When we perform these implicit instantiations, we do not carefully
- // keep track of the point of instantiation (C++ [temp.point]). This means
- // that name lookup that occurs within the template instantiation will
- // always happen at the end of the translation unit, so it will find
- // some names that should not be found. Although this is common behavior
- // for C++ compilers, it is technically wrong. In the future, we either need
- // to be able to filter the results of name lookup or we need to perform
- // template instantiations earlier.
- PerformPendingImplicitInstantiations();
-
- /// If DefinedUsedVTables ends up marking any virtual member
- /// functions it might lead to more pending template
- /// instantiations, which is why we need to loop here.
- if (!DefineUsedVTables())
- break;
- }
+void Sema::ActOnEndOfTranslationUnit() {
+ // At PCH writing, implicit instantiations and VTable handling info are
+ // stored and performed when the PCH is included.
+ if (CompleteTranslationUnit)
+ while (1) {
+ // C++: Perform implicit template instantiations.
+ //
+ // FIXME: When we perform these implicit instantiations, we do not
+ // carefully keep track of the point of instantiation (C++ [temp.point]).
+ // This means that name lookup that occurs within the template
+ // instantiation will always happen at the end of the translation unit,
+ // so it will find some names that should not be found. Although this is
+ // common behavior for C++ compilers, it is technically wrong. In the
+ // future, we either need to be able to filter the results of name lookup
+ // or we need to perform template instantiations earlier.
+ PerformPendingImplicitInstantiations();
+
+ /// If DefinedUsedVTables ends up marking any virtual member
+ /// functions it might lead to more pending template
+ /// instantiations, which is why we need to loop here.
+ if (!DefineUsedVTables())
+ break;
+ }
// Remove functions that turned out to be used.
UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(),