summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp31
-rw-r--r--clang/lib/AST/Type.cpp23
-rw-r--r--clang/lib/AST/TypeSerialization.cpp16
-rw-r--r--clang/lib/Parse/ParseDecl.cpp19
-rw-r--r--clang/lib/Sema/SemaType.cpp8
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 ...
OpenPOWER on IntegriCloud