[cfe-commits] r55417 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Basic/DiagnosticKinds.def include/clang/Basic/LangOptions.h include/clang/Parse/DeclSpec.h lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/AST/TypeSerialization.cpp lib/Parse/ParseDecl.cpp lib/Sema/SemaType.cpp test/Parser/block-pointer-decl.c

Steve Naroff snaroff at apple.com
Wed Aug 27 09:04:49 PDT 2008


Author: snaroff
Date: Wed Aug 27 11:04:49 2008
New Revision: 55417

URL: http://llvm.org/viewvc/llvm-project?rev=55417&view=rev
Log:
First wave of changes to support "blocks" (an extension to C).
This commit adds the declaration syntax (and associated type).

Added:
    cfe/trunk/test/Parser/block-pointer-decl.c
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Basic/LangOptions.h
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/AST/TypeSerialization.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed Aug 27 11:04:49 2008
@@ -51,6 +51,7 @@
   llvm::FoldingSet<ASQualType> ASQualTypes;
   llvm::FoldingSet<ComplexType> ComplexTypes;
   llvm::FoldingSet<PointerType> PointerTypes;
+  llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
   llvm::FoldingSet<ReferenceType> ReferenceTypes;
   llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
   llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
@@ -162,6 +163,10 @@
   /// getPointerType - Return the uniqued reference to the type for a pointer to
   /// the specified type.
   QualType getPointerType(QualType T);
+
+  /// getBlockPointerType - Return the uniqued reference to the type for a block
+  /// of the specified type.
+  QualType getBlockPointerType(QualType T);
   
   /// getReferenceType - Return the uniqued reference to the type for a
   /// reference to the specified type.

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Aug 27 11:04:49 2008
@@ -42,6 +42,7 @@
   class SourceLocation;
   class PointerLikeType;
   class PointerType;
+  class BlockPointerType;
   class ReferenceType;
   class VectorType;
   class ArrayType;
@@ -239,7 +240,8 @@
     TypeName, Tagged, ASQual,
     ObjCInterface, ObjCQualifiedInterface,
     ObjCQualifiedId,
-    TypeOfExp, TypeOfTyp // GNU typeof extension.
+    TypeOfExp, TypeOfTyp, // GNU typeof extension.
+    BlockPointer          // C extension
   };
 private:
   QualType CanonicalType;
@@ -319,6 +321,7 @@
   bool isFunctionType() const;
   bool isPointerLikeType() const; // Pointer or Reference.
   bool isPointerType() const;
+  bool isBlockPointerType() const;
   bool isReferenceType() const;
   bool isFunctionPointerType() const;
   bool isArrayType() const;
@@ -344,6 +347,7 @@
   const FunctionTypeProto *getAsFunctionTypeProto() const;   
   const PointerLikeType *getAsPointerLikeType() const; // Pointer or Reference.
   const PointerType *getAsPointerType() const;
+  const BlockPointerType *getAsBlockPointerType() const;
   const ReferenceType *getAsReferenceType() const;
   const RecordType *getAsRecordType() const;
   const RecordType *getAsStructureType() const;
@@ -568,6 +572,41 @@
   friend class Type;
 };
 
+/// BlockPointerType - pointer to a block type.
+/// This type is to represent types syntactically represented as
+/// "void (^)(int)", etc. Pointee is required to always be a function type.
+///
+class BlockPointerType : public Type, public llvm::FoldingSetNode {
+  QualType PointeeType;  // Block is some kind of pointer type
+  BlockPointerType(QualType Pointee, QualType CanonicalCls) :
+    Type(BlockPointer, CanonicalCls), PointeeType(Pointee) {
+  }
+  friend class ASTContext;  // ASTContext creates these.
+public:
+  
+  // Get the pointee type. Pointee is required to always be a function type.
+  QualType getPointeeType() const { return PointeeType; }
+
+  virtual void getAsStringInternal(std::string &InnerString) const;
+    
+  void Profile(llvm::FoldingSetNodeID &ID) {
+      Profile(ID, getPointeeType());
+  }
+  static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) {
+      ID.AddPointer(Pointee.getAsOpaquePtr());
+  }
+    
+  static bool classof(const Type *T) { 
+    return T->getTypeClass() == BlockPointer; 
+  }
+  static bool classof(const BlockPointerType *) { return true; }
+
+  protected:  
+    virtual void EmitImpl(llvm::Serializer& S) const;
+    static Type* CreateImpl(ASTContext& Context,llvm::Deserializer& D);
+    friend class Type;
+};
+
 /// ReferenceType - C++ 8.3.2 - Reference Declarators.
 ///
 class ReferenceType : public PointerLikeType, public llvm::FoldingSetNode {
@@ -1303,6 +1342,9 @@
 inline bool Type::isPointerType() const {
   return isa<PointerType>(CanonicalType.getUnqualifiedType()); 
 }
+inline bool Type::isBlockPointerType() const {
+    return isa<BlockPointerType>(CanonicalType); 
+}
 inline bool Type::isReferenceType() const {
   return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
 }

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Aug 27 11:04:49 2008
@@ -859,6 +859,10 @@
      "'%0' declared as a pointer to a reference")
 DIAG(err_illegal_decl_reference_to_reference, ERROR,
      "'%0' declared as a reference to a reference")
+DIAG(err_qualified_block_pointer_type, ERROR,
+     "qualifier specification on block pointer type not allowed")
+DIAG(err_nonfunction_block_type, ERROR,
+     "block pointer to non-function type is invalid")
 
 // Expressions.
 DIAG(ext_sizeof_function_type, EXTENSION,

Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Wed Aug 27 11:04:49 2008
@@ -48,6 +48,7 @@
 
   unsigned ThreadsafeStatics : 1; // Whether static initializers are protected
                                   // by lockis.
+  unsigned Blocks            : 1; // block extension to C
 private:
   unsigned GC : 2; // Objective-C Garbage Collection modes.  We declare
                    // this enum as unsigned because MSVC insists on making enums
@@ -66,6 +67,7 @@
     
     // FIXME: The default should be 1.
     ThreadsafeStatics = 0;
+    Blocks = 1;
   }
   
   GCMode getGCMode() const { return (GCMode) GC; }

Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Wed Aug 27 11:04:49 2008
@@ -376,7 +376,7 @@
 /// This is intended to be a small value object.
 struct DeclaratorChunk {
   enum {
-    Pointer, Reference, Array, Function
+    Pointer, Reference, Array, Function, BlockPointer
   } Kind;
   
   /// Loc - The place where this type was defined.
@@ -455,12 +455,20 @@
       delete[] ArgInfo;
     }
   };
-  
+
+  struct BlockPointerTypeInfo {
+    /// For now, sema will catch these as invalid.
+    /// The type qualifiers: const/volatile/restrict.
+    unsigned TypeQuals : 3;
+    void destroy() {}
+  };
+
   union {
-    PointerTypeInfo   Ptr;
-    ReferenceTypeInfo Ref;
-    ArrayTypeInfo     Arr;
-    FunctionTypeInfo  Fun;
+    PointerTypeInfo      Ptr;
+    ReferenceTypeInfo    Ref;
+    ArrayTypeInfo        Arr;
+    FunctionTypeInfo     Fun;
+    BlockPointerTypeInfo Cls;
   };
   
   
@@ -535,6 +543,16 @@
     }
     return I;
   }
+  /// getBlockPointer - Return a DeclaratorChunk for a block.
+  ///
+  static DeclaratorChunk getBlockPointer(unsigned TypeQuals, 
+                                         SourceLocation Loc) {
+    DeclaratorChunk I;
+    I.Kind          = BlockPointer;
+    I.Loc           = Loc;
+    I.Cls.TypeQuals = TypeQuals;
+    return I;
+  }
 };
 
 
@@ -619,6 +637,8 @@
         DeclTypeInfo[i].Fun.destroy();
       else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Pointer)
         DeclTypeInfo[i].Ptr.destroy();
+      else if (DeclTypeInfo[i].Kind == DeclaratorChunk::BlockPointer)
+        DeclTypeInfo[i].Cls.destroy();
       else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Reference)
         DeclTypeInfo[i].Ref.destroy();
       else if (DeclTypeInfo[i].Kind == DeclaratorChunk::Array)

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Aug 27 11:04:49 2008
@@ -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) {

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Aug 27 11:04:49 2008
@@ -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;
   

Modified: cfe/trunk/lib/AST/TypeSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeSerialization.cpp?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/lib/AST/TypeSerialization.cpp (original)
+++ cfe/trunk/lib/AST/TypeSerialization.cpp Wed Aug 27 11:04:49 2008
@@ -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
 //===----------------------------------------------------------------------===//
 

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Aug 27 11:04:49 2008
@@ -1111,14 +1111,15 @@
 void Parser::ParseDeclaratorInternal(Declarator &D) {
   tok::TokenKind Kind = Tok.getKind();
 
-  // Not a pointer or C++ reference.
-  if (Kind != tok::star && (Kind != tok::amp || !getLang().CPlusPlus))
+  // Not a pointer, C++ reference, or block.
+  if (Kind != tok::star && (Kind != tok::amp || !getLang().CPlusPlus) &&
+      (Kind != tok::caret || !getLang().Blocks))
     return ParseDirectDeclarator(D);
   
   // Otherwise, '*' -> pointer or '&' -> reference.
   SourceLocation Loc = ConsumeToken();  // Eat the * or &.
 
-  if (Kind == tok::star) {
+  if (Kind == tok::star || Kind == tok::caret) {
     // Is a pointer.
     DeclSpec DS;
     
@@ -1126,10 +1127,14 @@
   
     // Recursively parse the declarator.
     ParseDeclaratorInternal(D);
-
-    // Remember that we parsed a pointer type, and remember the type-quals.
-    D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
-                                              DS.TakeAttributes()));
+    if (Kind == tok::star)
+      // Remember that we parsed a pointer type, and remember the type-quals.
+      D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
+                                                DS.TakeAttributes()));
+    else
+      // Remember that we parsed a Block type, and remember the type-quals.
+      D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), 
+                                                     Loc));	
   } else {
     // Is a reference
     DeclSpec DS;

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=55417&r1=55416&r2=55417&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Aug 27 11:04:49 2008
@@ -253,6 +253,14 @@
     DeclaratorChunk &DeclType = D.getTypeObject(e-i-1);
     switch (DeclType.Kind) {
     default: assert(0 && "Unknown decltype!");
+    case DeclaratorChunk::BlockPointer:
+      if (DeclType.Cls.TypeQuals)
+        Diag(D.getIdentifierLoc(), diag::err_qualified_block_pointer_type);
+      if (!T.getTypePtr()->isFunctionType())
+        Diag(D.getIdentifierLoc(), diag::err_nonfunction_block_type);
+      else
+        T = Context.getBlockPointerType(T);
+      break;
     case DeclaratorChunk::Pointer:
       if (T->isReferenceType()) {
         // C++ 8.3.2p4: There shall be no ... pointers to references ...

Added: cfe/trunk/test/Parser/block-pointer-decl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/block-pointer-decl.c?rev=55417&view=auto

==============================================================================
--- cfe/trunk/test/Parser/block-pointer-decl.c (added)
+++ cfe/trunk/test/Parser/block-pointer-decl.c Wed Aug 27 11:04:49 2008
@@ -0,0 +1,18 @@
+// RUN: clang -fsyntax-only -verify -parse-noop %s
+
+struct blockStruct {
+  int (^a)(float, int);
+  int b;
+};
+
+int blockTaker (int (^myBlock)(int), int other_input)
+{
+  return 0;
+}
+
+int main (int argc, char **argv)
+{
+  int (^blockptr) (int);
+  return 0;
+}
+





More information about the cfe-commits mailing list