diff --git a/Driver/RewriteBlocks.cpp b/Driver/RewriteBlocks.cpp index 83bc4280c8..45c0715410 100644 --- a/Driver/RewriteBlocks.cpp +++ b/Driver/RewriteBlocks.cpp @@ -364,9 +364,11 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i, std::string S = "static " + RT.getAsString() + " __" + funcName + "_" + "block_func_" + utostr(i); + BlockDecl *BD = CE->getBlockDecl(); + if (isa(AFT)) { S += "()"; - } else if (CE->arg_empty()) { + } else if (BD->param_empty()) { S += "(" + StructRef + " *__cself)"; } else { const FunctionTypeProto *FT = cast(AFT); @@ -375,15 +377,15 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i, // first add the implicit argument. S += StructRef + " *__cself, "; std::string ParamStr; - for (BlockExpr::arg_iterator AI = CE->arg_begin(), - E = CE->arg_end(); AI != E; ++AI) { - if (AI != CE->arg_begin()) S += ", "; + for (BlockDecl::param_iterator AI = BD->param_begin(), + E = BD->param_end(); AI != E; ++AI) { + if (AI != BD->param_begin()) S += ", "; ParamStr = (*AI)->getName(); (*AI)->getType().getAsStringInternal(ParamStr); S += ParamStr; } if (FT->isVariadic()) { - if (!CE->arg_empty()) S += ", "; + if (!BD->param_empty()) S += ", "; S += "..."; } S += ')'; diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index b0acc4c1b7..88cbe85421 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -16,10 +16,12 @@ #include "clang/AST/DeclBase.h" #include "clang/Parse/AccessSpecifier.h" +#include "llvm/ADT/SmallVector.h" namespace clang { class Expr; class Stmt; +class CompoundStmt; class StringLiteral; class IdentifierInfo; @@ -981,6 +983,51 @@ protected: void ReadInRec(llvm::Deserializer& D, ASTContext& C); }; -} // end namespace clang +/// BlockDecl - This represents a block literal declaration, which is like an +/// unnamed FunctionDecl. For example: +/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } +/// +class BlockDecl : public Decl, public DeclContext { + llvm::SmallVector Args; + Stmt *Body; +protected: + BlockDecl(DeclContext *DC, SourceLocation CaretLoc, + ParmVarDecl **args, unsigned numargs, Stmt *body) + : Decl(Block, CaretLoc), DeclContext(Block), + Args(args, args+numargs), Body(body) {} + virtual ~BlockDecl(); + virtual void Destroy(ASTContext& C); + +public: + static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + ParmVarDecl **args, unsigned numargs, + CompoundStmt *body); + + SourceLocation getCaretLocation() const { return getLocation(); } + + Stmt *getBody() const { return Body; } + + /// arg_iterator - Iterate over the ParmVarDecl's for this block. + typedef llvm::SmallVector::const_iterator param_iterator; + bool param_empty() const { return Args.empty(); } + param_iterator param_begin() const { return Args.begin(); } + param_iterator param_end() const { return Args.end(); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return D->getKind() == Block; } + static bool classof(const TranslationUnitDecl *D) { return true; } + +protected: + /// EmitImpl - Serialize this BlockDecl. Called by Decl::Emit. + virtual void EmitImpl(llvm::Serializer& S) const; + + /// CreateImpl - Deserialize a BlockDecl. Called by Decl::Create. + static BlockDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C); + + friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C); +}; + +} // end namespace clang + #endif diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index d274fd381d..1ebd25c65f 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -27,6 +27,7 @@ class CXXRecordDecl; class EnumDecl; class ObjCMethodDecl; class ObjCInterfaceDecl; +class BlockDecl; /// Decl - This represents one declaration (or definition), e.g. a variable, /// typedef, function, struct, etc. @@ -81,6 +82,7 @@ public: ObjCPropertyImpl, LinkageSpec, FileScopeAsm, + Block, // [DeclContext] // For each non-leaf class, we now define a mapping to the first/last member // of the class, to allow efficient classof. @@ -243,6 +245,7 @@ protected: /// EnumDecl /// ObjCMethodDecl /// ObjCInterfaceDecl +/// BlockDecl /// class DeclContext { /// DeclKind - This indicates which class this is. @@ -295,6 +298,7 @@ public: bool isFunctionOrMethod() const { switch (DeclKind) { + case Decl::Block: case Decl::Function: case Decl::CXXMethod: case Decl::ObjCMethod: @@ -320,6 +324,7 @@ public: case Decl::Enum: case Decl::ObjCMethod: case Decl::ObjCInterface: + case Decl::Block: return true; default: if (D->getKind() >= Decl::FunctionFirst && @@ -339,6 +344,7 @@ public: static bool classof(const EnumDecl *D) { return true; } static bool classof(const ObjCMethodDecl *D) { return true; } static bool classof(const ObjCInterfaceDecl *D) { return true; } + static bool classof(const BlockDecl *D) { return true; } private: void EmitOutRec(llvm::Serializer& S) const; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 2b42424803..7fe172afc4 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -28,6 +28,7 @@ namespace clang { class IdentifierInfo; class ParmVarDecl; class ValueDecl; + class BlockDecl; /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt @@ -1498,36 +1499,29 @@ public: }; -/// BlockExpr - Represent a block literal with a syntax: +/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions. /// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } class BlockExpr : public Expr { - SourceLocation CaretLocation; - llvm::SmallVector Args; - Stmt *Body; +protected: + BlockDecl *TheBlock; public: - BlockExpr(SourceLocation caretloc, QualType ty, ParmVarDecl **args, - unsigned numargs, CompoundStmt *body) : Expr(BlockExprClass, ty), - CaretLocation(caretloc), Args(args, args+numargs), Body(body) {} + BlockExpr(BlockDecl *BD, QualType ty) : Expr(BlockExprClass, ty), + TheBlock(BD) {} - SourceLocation getCaretLocation() const { return CaretLocation; } + BlockDecl *getBlockDecl() { return TheBlock; } + + // Convenience functions for probing the underlying BlockDecl. + SourceLocation getCaretLocation() const; + const Stmt *getBody() const; + Stmt *getBody(); + + virtual SourceRange getSourceRange() const { + return SourceRange(getCaretLocation(), getBody()->getLocEnd()); + } /// getFunctionType - Return the underlying function type for this block. const FunctionType *getFunctionType() const; - const CompoundStmt *getBody() const { return cast(Body); } - CompoundStmt *getBody() { return cast(Body); } - - virtual SourceRange getSourceRange() const { - return SourceRange(getCaretLocation(), Body->getLocEnd()); - } - - /// arg_iterator - Iterate over the ParmVarDecl's for the arguments to this - /// block. - typedef llvm::SmallVector::const_iterator arg_iterator; - bool arg_empty() const { return Args.empty(); } - arg_iterator arg_begin() const { return Args.begin(); } - arg_iterator arg_end() const { return Args.end(); } - static bool classof(const Stmt *T) { return T->getStmtClass() == BlockExprClass; } @@ -1536,7 +1530,7 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); - + virtual void EmitImpl(llvm::Serializer& S) const; static BlockExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); }; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 3ddf81974b..c900a734ae 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -76,6 +76,13 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, TypeSpecStartLoc); } +BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, + ParmVarDecl **args, unsigned numargs, + CompoundStmt *body) { + void *Mem = C.getAllocator().Allocate(); + return new (Mem) BlockDecl(DC, L, args, numargs, body); +} + FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *BW) { void *Mem = C.getAllocator().Allocate(); @@ -285,3 +292,20 @@ FieldDecl *RecordDecl::getMember(IdentifierInfo *II) { return Members[i]; return 0; } + +//===----------------------------------------------------------------------===// +// BlockDecl Implementation +//===----------------------------------------------------------------------===// + +BlockDecl::~BlockDecl() { +} + +void BlockDecl::Destroy(ASTContext& C) { + if (Body) + Body->Destroy(C); + + for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I) + (*I)->Destroy(C); + + Decl::Destroy(C); +} diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index db179fec3e..b42950ffc0 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -49,6 +49,7 @@ static unsigned nObjCPropertyDecl = 0; static unsigned nObjCPropertyImplDecl = 0; static unsigned nLinkageSpecDecl = 0; static unsigned nFileScopeAsmDecl = 0; +static unsigned nBlockDecls = 0; static bool StatSwitch = false; @@ -77,6 +78,7 @@ const char *Decl::getDeclKindName() const { case Union: return "Union"; case Class: return "Class"; case Enum: return "Enum"; + case Block: return "Block"; } } @@ -221,6 +223,7 @@ void Decl::addDeclKind(Kind k) { case ObjCPropertyImpl: nObjCPropertyImplDecl++; break; case LinkageSpec: nLinkageSpecDecl++; break; case FileScopeAsm: nFileScopeAsmDecl++; break; + case Block: nBlockDecls++; break; case ImplicitParam: case TranslationUnit: break; diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp index 3f36e3ac89..2ebcb76fbf 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -441,6 +441,22 @@ FunctionDecl* FunctionDecl::CreateImpl(Deserializer& D, ASTContext& C) { return decl; } +void BlockDecl::EmitImpl(Serializer& S) const { + // FIXME: what about arguments? + S.Emit(getCaretLocation()); + S.EmitOwnedPtr(Body); +} + +BlockDecl* BlockDecl::CreateImpl(Deserializer& D, ASTContext& C) { + QualType Q = QualType::ReadVal(D); + SourceLocation L = SourceLocation::ReadVal(D); + /*CompoundStmt* BodyStmt = cast(*/D.ReadOwnedPtr(C)/*)*/; + assert(0 && "Cannot deserialize BlockBlockExpr yet"); + // FIXME: need to handle parameters. + //return new BlockBlockExpr(L, Q, BodyStmt); + return 0; +} + //===----------------------------------------------------------------------===// // RecordDecl Serialization. //===----------------------------------------------------------------------===// diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6cdaacd689..dfe412f4fc 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -217,6 +217,13 @@ const FunctionType *BlockExpr::getFunctionType() const { getPointeeType()->getAsFunctionType(); } +SourceLocation BlockExpr::getCaretLocation() const { + return TheBlock->getCaretLocation(); +} +const Stmt *BlockExpr::getBody() const { return TheBlock->getBody(); } +Stmt *BlockExpr::getBody() { return TheBlock->getBody(); } + + //===----------------------------------------------------------------------===// // Generic Expression Routines //===----------------------------------------------------------------------===// @@ -1400,8 +1407,8 @@ Stmt::child_iterator ObjCMessageExpr::child_end() { } // Blocks -Stmt::child_iterator BlockExpr::child_begin() { return &Body; } -Stmt::child_iterator BlockExpr::child_end() { return &Body+1; } +Stmt::child_iterator BlockExpr::child_begin() { return child_iterator(); } +Stmt::child_iterator BlockExpr::child_end() { return child_iterator(); } Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();} Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); } diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 844a3e8560..ba67a97deb 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -895,26 +895,27 @@ void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) { } void StmtPrinter::VisitBlockExpr(BlockExpr *Node) { + BlockDecl *BD = Node->getBlockDecl(); OS << "^"; const FunctionType *AFT = Node->getFunctionType(); if (isa(AFT)) { OS << "()"; - } else if (!Node->arg_empty() || cast(AFT)->isVariadic()) { - const FunctionTypeProto *FT = cast(AFT); + } else if (!BD->param_empty() || cast(AFT)->isVariadic()) { OS << '('; std::string ParamStr; - for (BlockExpr::arg_iterator AI = Node->arg_begin(), - E = Node->arg_end(); AI != E; ++AI) { - if (AI != Node->arg_begin()) OS << ", "; + for (BlockDecl::param_iterator AI = BD->param_begin(), + E = BD->param_end(); AI != E; ++AI) { + if (AI != BD->param_begin()) OS << ", "; ParamStr = (*AI)->getName(); (*AI)->getType().getAsStringInternal(ParamStr); OS << ParamStr; } + const FunctionTypeProto *FT = cast(AFT); if (FT->isVariadic()) { - if (!Node->arg_empty()) OS << ", "; + if (!BD->param_empty()) OS << ", "; OS << "..."; } OS << ')'; diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp index f72800d8ad..a4fd8c3567 100644 --- a/lib/AST/StmtSerialization.cpp +++ b/lib/AST/StmtSerialization.cpp @@ -1114,18 +1114,12 @@ ObjCStringLiteral* ObjCStringLiteral::CreateImpl(Deserializer& D, ASTContext& C) void BlockExpr::EmitImpl(Serializer& S) const { S.Emit(getType()); - S.Emit(getCaretLocation()); - S.EmitOwnedPtr(Body); + S.EmitOwnedPtr(TheBlock); } BlockExpr* BlockExpr::CreateImpl(Deserializer& D, ASTContext& C) { - QualType Q = QualType::ReadVal(D); - SourceLocation L = SourceLocation::ReadVal(D); - /*CompoundStmt* BodyStmt = cast(*/D.ReadOwnedPtr(C)/*)*/; - assert(0 && "Cannot deserialize BlockBlockExpr yet"); - // FIXME: need to handle parameters. - //return new BlockBlockExpr(L, Q, BodyStmt); - return 0; + QualType T = QualType::ReadVal(D); + return new BlockExpr(cast(D.ReadOwnedPtr(C)),T); } void BlockDeclRefExpr::EmitImpl(Serializer& S) const { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fa18ce313e..b8b614db07 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2931,8 +2931,11 @@ Sema::ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, StmtTy *body, BSI->isVariadic); BlockTy = Context.getBlockPointerType(BlockTy); - return new BlockExpr(CaretLoc, BlockTy, &BSI->Params[0], BSI->Params.size(), - Body.take()); + + BlockDecl *NewBD = BlockDecl::Create(Context, CurContext, CaretLoc, + &BSI->Params[0], BSI->Params.size(), + Body.take()); + return new BlockExpr(NewBD, BlockTy); } /// ExprsMatchFnType - return true if the Exprs in array Args have