diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 31 | ||||
| -rw-r--r-- | clang/lib/AST/Type.cpp | 23 | ||||
| -rw-r--r-- | clang/lib/AST/TypeSerialization.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 8 |
5 files changed, 89 insertions, 8 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index bb8743babd1..d17be725f5f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -610,6 +610,37 @@ QualType ASTContext::getPointerType(QualType T) { 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/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 84b369ca309..2c5a3f41bf9 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -231,6 +231,20 @@ const PointerType *Type::getAsPointerType() const { 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 @@ bool Type::isScalarType() const { } 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 @@ void PointerType::getAsStringInternal(std::string &S) const { 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/clang/lib/AST/TypeSerialization.cpp b/clang/lib/AST/TypeSerialization.cpp index 68ef1114a7c..96747268552 100644 --- a/clang/lib/AST/TypeSerialization.cpp +++ b/clang/lib/AST/TypeSerialization.cpp @@ -99,6 +99,10 @@ void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) { 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 @@ Type* ASQualType::CreateImpl(ASTContext& Context, Deserializer& D) { } //===----------------------------------------------------------------------===// +// 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 //===----------------------------------------------------------------------===// diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index def039b98d6..76fca9e885f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1111,14 +1111,15 @@ void Parser::ParseDeclarator(Declarator &D) { 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 @@ void Parser::ParseDeclaratorInternal(Declarator &D) { // 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; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c7876b1151a..209a0039880 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -253,6 +253,14 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { 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 ... |

