std::string S = "static " + RT.getAsString() + " __" +
funcName + "_" + "block_func_" + utostr(i);
+ BlockDecl *BD = CE->getBlockDecl();
+
if (isa<FunctionTypeNoProto>(AFT)) {
S += "()";
- } else if (CE->arg_empty()) {
+ } else if (BD->param_empty()) {
S += "(" + StructRef + " *__cself)";
} else {
const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
// 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 += ')';
#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;
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<ParmVarDecl*, 8> 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<ParmVarDecl*, 8>::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
class EnumDecl;
class ObjCMethodDecl;
class ObjCInterfaceDecl;
+class BlockDecl;
/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
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.
/// EnumDecl
/// ObjCMethodDecl
/// ObjCInterfaceDecl
+/// BlockDecl
///
class DeclContext {
/// DeclKind - This indicates which class this is.
bool isFunctionOrMethod() const {
switch (DeclKind) {
+ case Decl::Block:
case Decl::Function:
case Decl::CXXMethod:
case Decl::ObjCMethod:
case Decl::Enum:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
+ case Decl::Block:
return true;
default:
if (D->getKind() >= Decl::FunctionFirst &&
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;
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
};
-/// 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<ParmVarDecl*, 8> 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) {}
-
- SourceLocation getCaretLocation() const { return CaretLocation; }
-
- /// getFunctionType - Return the underlying function type for this block.
- const FunctionType *getFunctionType() const;
+ BlockExpr(BlockDecl *BD, QualType ty) : Expr(BlockExprClass, ty),
+ TheBlock(BD) {}
- const CompoundStmt *getBody() const { return cast<CompoundStmt>(Body); }
- CompoundStmt *getBody() { return cast<CompoundStmt>(Body); }
+ 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(), Body->getLocEnd());
+ return SourceRange(getCaretLocation(), getBody()->getLocEnd());
}
- /// arg_iterator - Iterate over the ParmVarDecl's for the arguments to this
- /// block.
- typedef llvm::SmallVector<ParmVarDecl*, 8>::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(); }
-
+ /// getFunctionType - Return the underlying function type for this block.
+ const FunctionType *getFunctionType() const;
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == BlockExprClass;
}
// 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);
};
TypeSpecStartLoc);
}
+BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ ParmVarDecl **args, unsigned numargs,
+ CompoundStmt *body) {
+ void *Mem = C.getAllocator().Allocate<BlockDecl>();
+ 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<FieldDecl>();
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);
+}
static unsigned nObjCPropertyImplDecl = 0;
static unsigned nLinkageSpecDecl = 0;
static unsigned nFileScopeAsmDecl = 0;
+static unsigned nBlockDecls = 0;
static bool StatSwitch = false;
case Union: return "Union";
case Class: return "Class";
case Enum: return "Enum";
+ case Block: return "Block";
}
}
case ObjCPropertyImpl: nObjCPropertyImplDecl++; break;
case LinkageSpec: nLinkageSpecDecl++; break;
case FileScopeAsm: nFileScopeAsmDecl++; break;
+ case Block: nBlockDecls++; break;
case ImplicitParam:
case TranslationUnit: break;
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<CompoundStmt>(*/D.ReadOwnedPtr<Stmt>(C)/*)*/;
+ assert(0 && "Cannot deserialize BlockBlockExpr yet");
+ // FIXME: need to handle parameters.
+ //return new BlockBlockExpr(L, Q, BodyStmt);
+ return 0;
+}
+
//===----------------------------------------------------------------------===//
// RecordDecl Serialization.
//===----------------------------------------------------------------------===//
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
//===----------------------------------------------------------------------===//
}
// 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(); }
}
void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
+ BlockDecl *BD = Node->getBlockDecl();
OS << "^";
const FunctionType *AFT = Node->getFunctionType();
if (isa<FunctionTypeNoProto>(AFT)) {
OS << "()";
- } else if (!Node->arg_empty() || cast<FunctionTypeProto>(AFT)->isVariadic()) {
- const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
+ } else if (!BD->param_empty() || cast<FunctionTypeProto>(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<FunctionTypeProto>(AFT);
if (FT->isVariadic()) {
- if (!Node->arg_empty()) OS << ", ";
+ if (!BD->param_empty()) OS << ", ";
OS << "...";
}
OS << ')';
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<CompoundStmt>(*/D.ReadOwnedPtr<Stmt>(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<BlockDecl>(D.ReadOwnedPtr<Decl>(C)),T);
}
void BlockDeclRefExpr::EmitImpl(Serializer& S) const {
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