Move key functions to a separate map.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90745 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index cc96a5d..490f338 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1104,6 +1104,20 @@
   return *NewEntry;
 }
 
+const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
+  RD = cast<CXXRecordDecl>(RD->getDefinition(*this));
+  assert(RD && "Cannot get key function for forward declarations!");
+  
+  const CXXMethodDecl *&Entry = KeyFunctions[RD];
+  if (!Entry) 
+    Entry = ASTRecordLayoutBuilder::ComputeKeyFunction(RD);
+  else
+    assert(Entry == ASTRecordLayoutBuilder::ComputeKeyFunction(RD) &&
+           "Key function changed!");
+  
+  return Entry;
+}
+
 //===----------------------------------------------------------------------===//
 //                   Type creation/memoization methods
 //===----------------------------------------------------------------------===//
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 0886739..550a32b 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -663,8 +663,61 @@
   Alignment = NewAlignment;
 }
 
-static const CXXMethodDecl *GetKeyFunction(const CXXRecordDecl *RD) {
-  if (!RD->isDynamicClass())
+const ASTRecordLayout *
+ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
+                                      const RecordDecl *D) {
+  ASTRecordLayoutBuilder Builder(Ctx);
+
+  Builder.Layout(D);
+
+  if (!isa<CXXRecordDecl>(D))
+    return new ASTRecordLayout(Builder.Size, Builder.Alignment, Builder.Size,
+                               Builder.FieldOffsets.data(),
+                               Builder.FieldOffsets.size());
+
+  // FIXME: This is not always correct. See the part about bitfields at
+  // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
+  // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
+  bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
+
+  // FIXME: This should be done in FinalizeLayout.
+  uint64_t DataSize =
+    IsPODForThePurposeOfLayout ? Builder.Size : Builder.DataSize;
+  uint64_t NonVirtualSize =
+    IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
+
+  return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
+                             Builder.FieldOffsets.data(),
+                             Builder.FieldOffsets.size(),
+                             NonVirtualSize,
+                             Builder.NonVirtualAlignment,
+                             Builder.PrimaryBase,
+                             Builder.Bases.data(),
+                             Builder.Bases.size(),
+                             Builder.VBases.data(),
+                             Builder.VBases.size());
+}
+
+const ASTRecordLayout *
+ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
+                                      const ObjCInterfaceDecl *D,
+                                      const ObjCImplementationDecl *Impl) {
+  ASTRecordLayoutBuilder Builder(Ctx);
+
+  Builder.Layout(D, Impl);
+
+  return new ASTRecordLayout(Builder.Size, Builder.Alignment,
+                             Builder.DataSize,
+                             Builder.FieldOffsets.data(),
+                             Builder.FieldOffsets.size());
+}
+
+const CXXMethodDecl *
+ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
+  assert(RD->isDynamicClass() && "Class does not have any virtual methods!");
+
+  // If a class isnt' polymorphic it doesn't have a key function.
+  if (!RD->isPolymorphic())
     return 0;
   
   for (CXXRecordDecl::method_iterator I = RD->method_begin(), 
@@ -692,54 +745,3 @@
   return 0;
 }
 
-const ASTRecordLayout *
-ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
-                                      const RecordDecl *D) {
-  ASTRecordLayoutBuilder Builder(Ctx);
-
-  Builder.Layout(D);
-
-  if (!isa<CXXRecordDecl>(D))
-    return new ASTRecordLayout(Builder.Size, Builder.Alignment, Builder.Size,
-                               Builder.FieldOffsets.data(),
-                               Builder.FieldOffsets.size());
-
-  // FIXME: This is not always correct. See the part about bitfields at
-  // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
-  // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
-  bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
-
-  // FIXME: This should be done in FinalizeLayout.
-  uint64_t DataSize =
-    IsPODForThePurposeOfLayout ? Builder.Size : Builder.DataSize;
-  uint64_t NonVirtualSize =
-    IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
-
-  const CXXMethodDecl *KeyFunction = GetKeyFunction(cast<CXXRecordDecl>(D));
-  
-  return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
-                             Builder.FieldOffsets.data(),
-                             Builder.FieldOffsets.size(),
-                             NonVirtualSize,
-                             Builder.NonVirtualAlignment,
-                             Builder.PrimaryBase,
-                             Builder.Bases.data(),
-                             Builder.Bases.size(),
-                             Builder.VBases.data(),
-                             Builder.VBases.size(),
-                             KeyFunction);
-}
-
-const ASTRecordLayout *
-ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
-                                      const ObjCInterfaceDecl *D,
-                                      const ObjCImplementationDecl *Impl) {
-  ASTRecordLayoutBuilder Builder(Ctx);
-
-  Builder.Layout(D, Impl);
-
-  return new ASTRecordLayout(Builder.Size, Builder.Alignment,
-                             Builder.DataSize,
-                             Builder.FieldOffsets.data(),
-                             Builder.FieldOffsets.size());
-}
diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h
index 69e0498..d4171d3 100644
--- a/lib/AST/RecordLayoutBuilder.h
+++ b/lib/AST/RecordLayoutBuilder.h
@@ -151,6 +151,7 @@
   static const ASTRecordLayout *ComputeLayout(ASTContext &Ctx,
                                               const ObjCInterfaceDecl *D,
                                             const ObjCImplementationDecl *Impl);
+  static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD);
 };
 
 } // end namespace clang