Add code to create the fast enumeration state type

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55572 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 95073bc..faf4cc6 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -94,6 +94,8 @@
   QualType ObjCConstantStringType;
   RecordDecl *CFConstantStringTypeDecl;
 
+  RecordDecl *ObjCFastEnumerationStateTypeDecl;
+  
   TranslationUnitDecl *TUDecl;
 
   /// SourceMgr - The associated SourceManager object.
@@ -268,6 +270,9 @@
     return ObjCConstantStringType; 
   }
 
+  //// This gets the struct used to keep track of fast enumerations.
+  QualType getObjCFastEnumerationStateType();
+  
   // Return the ObjC type encoding for a given type.
   void getObjCEncodingForType(QualType t, std::string &S, 
                               llvm::SmallVector<const RecordType*,8> &RT) const;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index ad82090..2acdfac 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -30,7 +30,8 @@
 ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
                        IdentifierTable &idents, SelectorTable &sels,
                        unsigned size_reserve) : 
-  CFConstantStringTypeDecl(0), SourceMgr(SM), LangOpts(LOpts), Target(t), 
+  CFConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0),
+  SourceMgr(SM), LangOpts(LOpts), Target(t), 
   Idents(idents), Selectors(sels) 
 {  
   if (size_reserve > 0) Types.reserve(size_reserve);    
@@ -1371,6 +1372,32 @@
   return getTagDeclType(CFConstantStringTypeDecl);
 }
 
+QualType ASTContext::getObjCFastEnumerationStateType()
+{
+  if (!ObjCFastEnumerationStateTypeDecl) {
+    QualType FieldTypes[] = {
+      UnsignedLongTy,
+      getPointerType(ObjCIdType),
+      getPointerType(UnsignedLongTy),
+      getConstantArrayType(UnsignedLongTy,
+                           llvm::APInt(32, 5), ArrayType::Normal, 0)
+    };
+    
+    FieldDecl *FieldDecls[4];
+    for (size_t i = 0; i < 4; ++i)
+      FieldDecls[i] = FieldDecl::Create(*this, SourceLocation(), 0, 
+                                        FieldTypes[i]);
+    
+    ObjCFastEnumerationStateTypeDecl =
+      RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+                         &Idents.get("__objcFastEnumerationState"), 0);
+    
+    ObjCFastEnumerationStateTypeDecl->defineBody(FieldDecls, 4);
+  }
+  
+  return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
+}
+
 // This returns true if a type has been typedefed to BOOL:
 // typedef <type> BOOL;
 static bool isTypeTypedefedAsBOOL(QualType T) {