First wave of changes to support "blocks" (an extension to C).
This commit adds the declaration syntax (and associated type).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55417 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index bb8743b..d17be72 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -610,6 +610,37 @@
   return QualType(New, 0);
 }
 
+/// getBlockPointerType - Return the uniqued reference to the type for 
+/// a pointer to the specified block.
+QualType ASTContext::getBlockPointerType(QualType T) {
+  assert(T->isFunctionType() && "closure of function types only");
+  // Unique pointers, to guarantee there is only one closure of a particular
+  // structure.
+  llvm::FoldingSetNodeID ID;
+  BlockPointerType::Profile(ID, T);
+  
+  void *InsertPos = 0;
+  if (BlockPointerType *PT =
+        BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
+    return QualType(PT, 0);
+  
+  // If the closure pointee type isn't canonical, this won't be a canonical 
+  // type either so fill in the canonical type field.
+  QualType Canonical;
+  if (!T->isCanonical()) {
+    Canonical = getBlockPointerType(getCanonicalType(T));
+    
+    // Get the new insert position for the node we care about.
+    BlockPointerType *NewIP =
+      BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+    assert(NewIP == 0 && "Shouldn't be in the map!");
+  }
+  BlockPointerType *New = new BlockPointerType(T, Canonical);
+  Types.push_back(New);
+  BlockPointerTypes.InsertNode(New, InsertPos);
+  return QualType(New, 0);
+}
+
 /// getReferenceType - Return the uniqued reference to the type for a reference
 /// to the specified type.
 QualType ASTContext::getReferenceType(QualType T) {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 84b369c..2c5a3f4 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -231,6 +231,20 @@
   return getDesugaredType()->getAsPointerType();
 }
 
+const BlockPointerType *Type::getAsBlockPointerType() const {
+  // If this is directly a block pointer type, return it.
+  if (const BlockPointerType *PTy = dyn_cast<BlockPointerType>(this))
+    return PTy;
+  
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<BlockPointerType>(CanonicalType))
+    return 0;
+  
+  // If this is a typedef for a block pointer type, strip the typedef off 
+  // without losing all typedef information.
+  return getDesugaredType()->getAsBlockPointerType();
+}
+
 const ReferenceType *Type::getAsReferenceType() const {
   // If this is directly a reference type, return it.
   if (const ReferenceType *RTy = dyn_cast<ReferenceType>(this))
@@ -574,7 +588,9 @@
   }
   if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
     return ASQT->getBaseType()->isScalarType();
-  return isa<PointerType>(CanonicalType) || isa<ComplexType>(CanonicalType) ||
+  return isa<PointerType>(CanonicalType) ||
+         isa<BlockPointerType>(CanonicalType) ||
+         isa<ComplexType>(CanonicalType) ||
          isa<ObjCQualifiedIdType>(CanonicalType);
 }
 
@@ -831,6 +847,11 @@
   getPointeeType().getAsStringInternal(S);
 }
 
+void BlockPointerType::getAsStringInternal(std::string &S) const {
+  S = '^' + S;
+  PointeeType.getAsStringInternal(S);
+}
+
 void ReferenceType::getAsStringInternal(std::string &S) const {
   S = '&' + S;
   
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index 68ef111..9674726 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -99,6 +99,10 @@
     case Type::Pointer:
       D.RegisterPtr(PtrID,PointerType::CreateImpl(Context,D));
       break;
+
+    case Type::BlockPointer:
+      D.RegisterPtr(PtrID,BlockPointerType::CreateImpl(Context,D));
+      break;
       
     case Type::Tagged:
       D.RegisterPtr(PtrID,TagType::CreateImpl(Context,D));
@@ -130,6 +134,18 @@
 }
 
 //===----------------------------------------------------------------------===//
+// BlockPointerType
+//===----------------------------------------------------------------------===//
+
+void BlockPointerType::EmitImpl(Serializer& S) const {
+  S.Emit(getPointeeType());
+}
+
+Type* BlockPointerType::CreateImpl(ASTContext& Context, Deserializer& D) {
+  return Context.getBlockPointerType(QualType::ReadVal(D)).getTypePtr();
+}
+
+//===----------------------------------------------------------------------===//
 // ComplexType
 //===----------------------------------------------------------------------===//