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;
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);
}
}
}
}
- // 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;
-// 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*) {
}