aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2010-08-05 09:48:16 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2010-08-05 09:48:16 +0000
commit0e0363866792b309d70e9c8e92b4c239773af89c (patch)
tree3df1d201ce92c06a6812878941c859b41d9c7092
parent72b90571b1783b17c3f2204cec5ca440edc38bee (diff)
Store the pending implicit instantiations in the PCH and perform them at the end of the translation unit that
included the PCH, as God intended. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110324 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Frontend/PCHBitCodes.h5
-rw-r--r--include/clang/Frontend/PCHReader.h3
-rw-r--r--lib/Frontend/PCHReader.cpp19
-rw-r--r--lib/Frontend/PCHWriter.cpp16
-rw-r--r--lib/Sema/Sema.cpp43
-rw-r--r--test/PCH/cxx-templates.cpp3
-rw-r--r--test/PCH/cxx-templates.h11
7 files changed, 79 insertions, 21 deletions
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
index 37337963a1..7605670f0e 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -253,7 +253,10 @@ namespace clang {
SEMA_DECL_REFS = 30,
/// \brief Record code for weak undeclared identifiers.
- WEAK_UNDECLARED_IDENTIFIERS = 31
+ WEAK_UNDECLARED_IDENTIFIERS = 31,
+
+ /// \brief Record code for pending implicit instantiations.
+ PENDING_IMPLICIT_INSTANTIATIONS = 32
};
/// \brief Record types used within a source manager block.
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
index 76975a0e01..fc63e82287 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Frontend/PCHReader.h
@@ -397,6 +397,9 @@ private:
/// \brief The set of dynamic CXXRecord declarations stored in the PCH file.
llvm::SmallVector<uint64_t, 16> DynamicClasses;
+ /// \brief The set of pending implicit instantiations stored in the PCH file.
+ llvm::SmallVector<uint64_t, 64> PendingImplicitInstantiations;
+
/// \brief The set of Sema declaration references, stored in PCH.
llvm::SmallVector<uint64_t, 4> SemaDeclRefs;
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(),
diff --git a/test/PCH/cxx-templates.cpp b/test/PCH/cxx-templates.cpp
index 8e89b1da46..0749fc31e3 100644
--- a/test/PCH/cxx-templates.cpp
+++ b/test/PCH/cxx-templates.cpp
@@ -7,6 +7,7 @@
// RUN: %clang_cc1 -include-pch %t -verify %s -ast-dump 1>/dev/null
// RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s
+// CHECK: define weak_odr void @_ZN2S4IiE1mEv
// CHECK: define linkonce_odr void @_ZN2S3IiE1mEv
struct A {
@@ -30,3 +31,5 @@ void test() {
S3<int> s3;
s3.m();
}
+
+template struct S4<int>;
diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h
index 91d53d3060..978d768acc 100644
--- a/test/PCH/cxx-templates.h
+++ b/test/PCH/cxx-templates.h
@@ -124,3 +124,14 @@ struct S3 {
template <typename T>
inline void S3<T>::m() { }
+
+template <typename T>
+struct S4 {
+ void m() { }
+};
+extern template struct S4<int>;
+
+void S4ImplicitInst() {
+ S4<int> s;
+ s.m();
+}