diff options
-rw-r--r-- | clang/include/clang/AST/ASTContext.h | 2 | ||||
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 23 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 6 | ||||
-rw-r--r-- | clang/test/PCH/check-deserializations.cpp | 19 |
4 files changed, 28 insertions, 22 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 06264efa068..6f27fbee0e7 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -148,7 +148,7 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable TypeInfoMap MemoizedTypeInfo; /// \brief A cache mapping from CXXRecordDecls to key functions. - llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions; + llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr> KeyFunctions; /// \brief Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 5df372639da..e5222c971e3 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2438,32 +2438,31 @@ const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) assert(RD->getDefinition() && "Cannot get key function for forward decl!"); RD = cast<CXXRecordDecl>(RD->getDefinition()); - const CXXMethodDecl *&entry = KeyFunctions[RD]; - if (!entry) { - entry = computeKeyFunction(*this, RD); - } + LazyDeclPtr &Entry = KeyFunctions[RD]; + if (!Entry) + Entry = const_cast<CXXMethodDecl*>(computeKeyFunction(*this, RD)); - return entry; + return cast_or_null<CXXMethodDecl>(Entry.get(getExternalSource())); } -void ASTContext::setNonKeyFunction(const CXXMethodDecl *method) { - assert(method == method->getFirstDeclaration() && +void ASTContext::setNonKeyFunction(const CXXMethodDecl *Method) { + assert(Method == Method->getFirstDeclaration() && "not working with method declaration from class definition"); // Look up the cache entry. Since we're working with the first // declaration, its parent must be the class definition, which is // the correct key for the KeyFunctions hash. - llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*>::iterator - i = KeyFunctions.find(method->getParent()); + llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr>::iterator + I = KeyFunctions.find(Method->getParent()); // If it's not cached, there's nothing to do. - if (i == KeyFunctions.end()) return; + if (I == KeyFunctions.end()) return; // If it is cached, check whether it's the target method, and if so, // remove it from the cache. - if (i->second == method) { + if (I->second.get(getExternalSource()) == Method) { // FIXME: remember that we did this for module / chained PCH state? - KeyFunctions.erase(i); + KeyFunctions.erase(I); } } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 3c93340f5ef..a224aefa8fa 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1276,11 +1276,11 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { } } - // Load the key function to avoid deserializing every method so we can + // Lazily load the key function to avoid deserializing every method so we can // compute it. if (D->IsCompleteDefinition) { - if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx)) - C.KeyFunctions[D] = Key; + if (DeclID KeyFn = ReadDeclID(Record, Idx)) + C.KeyFunctions[D] = KeyFn; } return Redecl; diff --git a/clang/test/PCH/check-deserializations.cpp b/clang/test/PCH/check-deserializations.cpp index 9f73c95c541..66eb5b480b9 100644 --- a/clang/test/PCH/check-deserializations.cpp +++ b/clang/test/PCH/check-deserializations.cpp @@ -1,18 +1,25 @@ -// RUN: %clang_cc1 -emit-pch -o %t %s -// RUN: %clang_cc1 -error-on-deserialized-decl S1_method -include-pch %t -emit-llvm-only %s +// RUN: %clang_cc1 -emit-pch -o %t.1 %s +// RUN: %clang_cc1 -error-on-deserialized-decl S1_keyfunc -include-pch %t.1 -emit-pch -o %t.2 %s +// RUN: %clang_cc1 -error-on-deserialized-decl S1_method -include-pch %t.2 -emit-llvm-only %s -#ifndef HEADER -#define HEADER +#ifndef HEADER1 +#define HEADER1 // Header. struct S1 { - void S1_method(); // This should not be deserialized. + void S1_method(); virtual void S1_keyfunc(); }; +#elif !defined(HEADER2) +#define HEADER2 + +// Chained PCH. +S1 *p; #else -// Using the header. + +// Using the headers. void test(S1*) { } |