Add ObjCInterface layout support.
Reuse RecordLayout.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51968 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 6b5eaa1..4a1fb39 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -295,6 +295,13 @@
     Align = EltInfo.second;
     break;
   }
+  case Type::ObjCInterface: {
+    ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
+    const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
+    Width = Layout.getSize();
+    Align = Layout.getAlignment();
+    break;
+  }
   case Type::Tagged: {
     if (EnumType *ET = dyn_cast<EnumType>(cast<TagType>(T)))
       return getTypeInfo(ET->getDecl()->getIntegerType());
@@ -386,6 +393,42 @@
   Alignment = std::max(Alignment, FieldAlign);
 }
 
+
+/// getASTObjcInterfaceLayout - Get or compute information about the layout of the
+/// specified Objective C, which indicates its size and ivar
+/// position information.
+const ASTRecordLayout &
+ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) {
+  // Look up this layout, if already laid out, return what we have.
+  const ASTRecordLayout *&Entry = ASTObjCInterfaces[D];
+  if (Entry) return *Entry;
+
+  // Allocate and assign into ASTRecordLayouts here.  The "Entry" reference can
+  // be invalidated (dangle) if the ASTRecordLayouts hashtable is inserted into.
+  ASTRecordLayout *NewEntry = new ASTRecordLayout();
+  Entry = NewEntry;
+
+  NewEntry->InitializeLayout(D->ivar_size());
+  bool IsPacked = D->getAttr<PackedAttr>();
+
+  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+    NewEntry->SetAlignment(std::max(NewEntry->getAlignment(), 
+                                    AA->getAlignment()));
+
+  // Layout each ivar sequentially.
+  unsigned i = 0;
+  for (ObjCInterfaceDecl::ivar_iterator IVI = D->ivar_begin(), 
+       IVE = D->ivar_end(); IVI != IVE; ++IVI) {
+    const ObjCIvarDecl* Ivar = (*IVI);
+    NewEntry->LayoutField(Ivar, i++, false, IsPacked, *this);
+  }
+
+  // Finally, round the size of the total struct up to the alignment of the
+  // struct itself.
+  NewEntry->FinalizeLayout();
+  return *NewEntry;
+}
+
 /// getASTRecordLayout - Get or compute information about the layout of the
 /// specified record (struct/union/class), which indicates its size and field
 /// position information.