forked from OSchip/llvm-project
- Add BlockDecl AST node.
- Modify BlockExpr to reference the BlockDecl. This is "cleanup" necessary to improve our lookup semantics for blocks (to fix <rdar://problem/6272905> clang block rewriter: parameter to function not imported into block?). Still some follow-up work to finish this (forthcoming). llvm-svn: 57298
This commit is contained in:
parent
d83529e8c4
commit
415d3d570a
|
@ -364,9 +364,11 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
|
||||||
std::string S = "static " + RT.getAsString() + " __" +
|
std::string S = "static " + RT.getAsString() + " __" +
|
||||||
funcName + "_" + "block_func_" + utostr(i);
|
funcName + "_" + "block_func_" + utostr(i);
|
||||||
|
|
||||||
|
BlockDecl *BD = CE->getBlockDecl();
|
||||||
|
|
||||||
if (isa<FunctionTypeNoProto>(AFT)) {
|
if (isa<FunctionTypeNoProto>(AFT)) {
|
||||||
S += "()";
|
S += "()";
|
||||||
} else if (CE->arg_empty()) {
|
} else if (BD->param_empty()) {
|
||||||
S += "(" + StructRef + " *__cself)";
|
S += "(" + StructRef + " *__cself)";
|
||||||
} else {
|
} else {
|
||||||
const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
|
const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
|
||||||
|
@ -375,15 +377,15 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
|
||||||
// first add the implicit argument.
|
// first add the implicit argument.
|
||||||
S += StructRef + " *__cself, ";
|
S += StructRef + " *__cself, ";
|
||||||
std::string ParamStr;
|
std::string ParamStr;
|
||||||
for (BlockExpr::arg_iterator AI = CE->arg_begin(),
|
for (BlockDecl::param_iterator AI = BD->param_begin(),
|
||||||
E = CE->arg_end(); AI != E; ++AI) {
|
E = BD->param_end(); AI != E; ++AI) {
|
||||||
if (AI != CE->arg_begin()) S += ", ";
|
if (AI != BD->param_begin()) S += ", ";
|
||||||
ParamStr = (*AI)->getName();
|
ParamStr = (*AI)->getName();
|
||||||
(*AI)->getType().getAsStringInternal(ParamStr);
|
(*AI)->getType().getAsStringInternal(ParamStr);
|
||||||
S += ParamStr;
|
S += ParamStr;
|
||||||
}
|
}
|
||||||
if (FT->isVariadic()) {
|
if (FT->isVariadic()) {
|
||||||
if (!CE->arg_empty()) S += ", ";
|
if (!BD->param_empty()) S += ", ";
|
||||||
S += "...";
|
S += "...";
|
||||||
}
|
}
|
||||||
S += ')';
|
S += ')';
|
||||||
|
|
|
@ -16,10 +16,12 @@
|
||||||
|
|
||||||
#include "clang/AST/DeclBase.h"
|
#include "clang/AST/DeclBase.h"
|
||||||
#include "clang/Parse/AccessSpecifier.h"
|
#include "clang/Parse/AccessSpecifier.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
class Expr;
|
class Expr;
|
||||||
class Stmt;
|
class Stmt;
|
||||||
|
class CompoundStmt;
|
||||||
class StringLiteral;
|
class StringLiteral;
|
||||||
class IdentifierInfo;
|
class IdentifierInfo;
|
||||||
|
|
||||||
|
@ -981,6 +983,51 @@ protected:
|
||||||
void ReadInRec(llvm::Deserializer& D, ASTContext& C);
|
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
|
#endif
|
||||||
|
|
|
@ -27,6 +27,7 @@ class CXXRecordDecl;
|
||||||
class EnumDecl;
|
class EnumDecl;
|
||||||
class ObjCMethodDecl;
|
class ObjCMethodDecl;
|
||||||
class ObjCInterfaceDecl;
|
class ObjCInterfaceDecl;
|
||||||
|
class BlockDecl;
|
||||||
|
|
||||||
/// Decl - This represents one declaration (or definition), e.g. a variable,
|
/// Decl - This represents one declaration (or definition), e.g. a variable,
|
||||||
/// typedef, function, struct, etc.
|
/// typedef, function, struct, etc.
|
||||||
|
@ -81,6 +82,7 @@ public:
|
||||||
ObjCPropertyImpl,
|
ObjCPropertyImpl,
|
||||||
LinkageSpec,
|
LinkageSpec,
|
||||||
FileScopeAsm,
|
FileScopeAsm,
|
||||||
|
Block, // [DeclContext]
|
||||||
|
|
||||||
// For each non-leaf class, we now define a mapping to the first/last member
|
// For each non-leaf class, we now define a mapping to the first/last member
|
||||||
// of the class, to allow efficient classof.
|
// of the class, to allow efficient classof.
|
||||||
|
@ -243,6 +245,7 @@ protected:
|
||||||
/// EnumDecl
|
/// EnumDecl
|
||||||
/// ObjCMethodDecl
|
/// ObjCMethodDecl
|
||||||
/// ObjCInterfaceDecl
|
/// ObjCInterfaceDecl
|
||||||
|
/// BlockDecl
|
||||||
///
|
///
|
||||||
class DeclContext {
|
class DeclContext {
|
||||||
/// DeclKind - This indicates which class this is.
|
/// DeclKind - This indicates which class this is.
|
||||||
|
@ -295,6 +298,7 @@ public:
|
||||||
|
|
||||||
bool isFunctionOrMethod() const {
|
bool isFunctionOrMethod() const {
|
||||||
switch (DeclKind) {
|
switch (DeclKind) {
|
||||||
|
case Decl::Block:
|
||||||
case Decl::Function:
|
case Decl::Function:
|
||||||
case Decl::CXXMethod:
|
case Decl::CXXMethod:
|
||||||
case Decl::ObjCMethod:
|
case Decl::ObjCMethod:
|
||||||
|
@ -320,6 +324,7 @@ public:
|
||||||
case Decl::Enum:
|
case Decl::Enum:
|
||||||
case Decl::ObjCMethod:
|
case Decl::ObjCMethod:
|
||||||
case Decl::ObjCInterface:
|
case Decl::ObjCInterface:
|
||||||
|
case Decl::Block:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
if (D->getKind() >= Decl::FunctionFirst &&
|
if (D->getKind() >= Decl::FunctionFirst &&
|
||||||
|
@ -339,6 +344,7 @@ public:
|
||||||
static bool classof(const EnumDecl *D) { return true; }
|
static bool classof(const EnumDecl *D) { return true; }
|
||||||
static bool classof(const ObjCMethodDecl *D) { return true; }
|
static bool classof(const ObjCMethodDecl *D) { return true; }
|
||||||
static bool classof(const ObjCInterfaceDecl *D) { return true; }
|
static bool classof(const ObjCInterfaceDecl *D) { return true; }
|
||||||
|
static bool classof(const BlockDecl *D) { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EmitOutRec(llvm::Serializer& S) const;
|
void EmitOutRec(llvm::Serializer& S) const;
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace clang {
|
||||||
class IdentifierInfo;
|
class IdentifierInfo;
|
||||||
class ParmVarDecl;
|
class ParmVarDecl;
|
||||||
class ValueDecl;
|
class ValueDecl;
|
||||||
|
class BlockDecl;
|
||||||
|
|
||||||
/// Expr - This represents one expression. Note that Expr's are subclasses of
|
/// 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
|
/// 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 }
|
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
|
||||||
class BlockExpr : public Expr {
|
class BlockExpr : public Expr {
|
||||||
SourceLocation CaretLocation;
|
protected:
|
||||||
llvm::SmallVector<ParmVarDecl*, 8> Args;
|
BlockDecl *TheBlock;
|
||||||
Stmt *Body;
|
|
||||||
public:
|
public:
|
||||||
BlockExpr(SourceLocation caretloc, QualType ty, ParmVarDecl **args,
|
BlockExpr(BlockDecl *BD, QualType ty) : Expr(BlockExprClass, ty),
|
||||||
unsigned numargs, CompoundStmt *body) : Expr(BlockExprClass, ty),
|
TheBlock(BD) {}
|
||||||
CaretLocation(caretloc), Args(args, args+numargs), Body(body) {}
|
|
||||||
|
|
||||||
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.
|
/// getFunctionType - Return the underlying function type for this block.
|
||||||
const FunctionType *getFunctionType() const;
|
const FunctionType *getFunctionType() const;
|
||||||
|
|
||||||
const CompoundStmt *getBody() const { return cast<CompoundStmt>(Body); }
|
|
||||||
CompoundStmt *getBody() { return cast<CompoundStmt>(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<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(); }
|
|
||||||
|
|
||||||
static bool classof(const Stmt *T) {
|
static bool classof(const Stmt *T) {
|
||||||
return T->getStmtClass() == BlockExprClass;
|
return T->getStmtClass() == BlockExprClass;
|
||||||
}
|
}
|
||||||
|
@ -1536,7 +1530,7 @@ public:
|
||||||
// Iterators
|
// Iterators
|
||||||
virtual child_iterator child_begin();
|
virtual child_iterator child_begin();
|
||||||
virtual child_iterator child_end();
|
virtual child_iterator child_end();
|
||||||
|
|
||||||
virtual void EmitImpl(llvm::Serializer& S) const;
|
virtual void EmitImpl(llvm::Serializer& S) const;
|
||||||
static BlockExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
static BlockExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
||||||
};
|
};
|
||||||
|
|
|
@ -76,6 +76,13 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
||||||
TypeSpecStartLoc);
|
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,
|
FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L,
|
||||||
IdentifierInfo *Id, QualType T, Expr *BW) {
|
IdentifierInfo *Id, QualType T, Expr *BW) {
|
||||||
void *Mem = C.getAllocator().Allocate<FieldDecl>();
|
void *Mem = C.getAllocator().Allocate<FieldDecl>();
|
||||||
|
@ -285,3 +292,20 @@ FieldDecl *RecordDecl::getMember(IdentifierInfo *II) {
|
||||||
return Members[i];
|
return Members[i];
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ static unsigned nObjCPropertyDecl = 0;
|
||||||
static unsigned nObjCPropertyImplDecl = 0;
|
static unsigned nObjCPropertyImplDecl = 0;
|
||||||
static unsigned nLinkageSpecDecl = 0;
|
static unsigned nLinkageSpecDecl = 0;
|
||||||
static unsigned nFileScopeAsmDecl = 0;
|
static unsigned nFileScopeAsmDecl = 0;
|
||||||
|
static unsigned nBlockDecls = 0;
|
||||||
|
|
||||||
static bool StatSwitch = false;
|
static bool StatSwitch = false;
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ const char *Decl::getDeclKindName() const {
|
||||||
case Union: return "Union";
|
case Union: return "Union";
|
||||||
case Class: return "Class";
|
case Class: return "Class";
|
||||||
case Enum: return "Enum";
|
case Enum: return "Enum";
|
||||||
|
case Block: return "Block";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +223,7 @@ void Decl::addDeclKind(Kind k) {
|
||||||
case ObjCPropertyImpl: nObjCPropertyImplDecl++; break;
|
case ObjCPropertyImpl: nObjCPropertyImplDecl++; break;
|
||||||
case LinkageSpec: nLinkageSpecDecl++; break;
|
case LinkageSpec: nLinkageSpecDecl++; break;
|
||||||
case FileScopeAsm: nFileScopeAsmDecl++; break;
|
case FileScopeAsm: nFileScopeAsmDecl++; break;
|
||||||
|
case Block: nBlockDecls++; break;
|
||||||
case ImplicitParam:
|
case ImplicitParam:
|
||||||
case TranslationUnit: break;
|
case TranslationUnit: break;
|
||||||
|
|
||||||
|
|
|
@ -441,6 +441,22 @@ FunctionDecl* FunctionDecl::CreateImpl(Deserializer& D, ASTContext& C) {
|
||||||
return decl;
|
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.
|
// RecordDecl Serialization.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -217,6 +217,13 @@ const FunctionType *BlockExpr::getFunctionType() const {
|
||||||
getPointeeType()->getAsFunctionType();
|
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
|
// Generic Expression Routines
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -1400,8 +1407,8 @@ Stmt::child_iterator ObjCMessageExpr::child_end() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blocks
|
// Blocks
|
||||||
Stmt::child_iterator BlockExpr::child_begin() { return &Body; }
|
Stmt::child_iterator BlockExpr::child_begin() { return child_iterator(); }
|
||||||
Stmt::child_iterator BlockExpr::child_end() { return &Body+1; }
|
Stmt::child_iterator BlockExpr::child_end() { return child_iterator(); }
|
||||||
|
|
||||||
Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();}
|
Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();}
|
||||||
Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); }
|
Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); }
|
||||||
|
|
|
@ -895,26 +895,27 @@ void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
|
void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
|
||||||
|
BlockDecl *BD = Node->getBlockDecl();
|
||||||
OS << "^";
|
OS << "^";
|
||||||
|
|
||||||
const FunctionType *AFT = Node->getFunctionType();
|
const FunctionType *AFT = Node->getFunctionType();
|
||||||
|
|
||||||
if (isa<FunctionTypeNoProto>(AFT)) {
|
if (isa<FunctionTypeNoProto>(AFT)) {
|
||||||
OS << "()";
|
OS << "()";
|
||||||
} else if (!Node->arg_empty() || cast<FunctionTypeProto>(AFT)->isVariadic()) {
|
} else if (!BD->param_empty() || cast<FunctionTypeProto>(AFT)->isVariadic()) {
|
||||||
const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
|
|
||||||
OS << '(';
|
OS << '(';
|
||||||
std::string ParamStr;
|
std::string ParamStr;
|
||||||
for (BlockExpr::arg_iterator AI = Node->arg_begin(),
|
for (BlockDecl::param_iterator AI = BD->param_begin(),
|
||||||
E = Node->arg_end(); AI != E; ++AI) {
|
E = BD->param_end(); AI != E; ++AI) {
|
||||||
if (AI != Node->arg_begin()) OS << ", ";
|
if (AI != BD->param_begin()) OS << ", ";
|
||||||
ParamStr = (*AI)->getName();
|
ParamStr = (*AI)->getName();
|
||||||
(*AI)->getType().getAsStringInternal(ParamStr);
|
(*AI)->getType().getAsStringInternal(ParamStr);
|
||||||
OS << ParamStr;
|
OS << ParamStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FunctionTypeProto *FT = cast<FunctionTypeProto>(AFT);
|
||||||
if (FT->isVariadic()) {
|
if (FT->isVariadic()) {
|
||||||
if (!Node->arg_empty()) OS << ", ";
|
if (!BD->param_empty()) OS << ", ";
|
||||||
OS << "...";
|
OS << "...";
|
||||||
}
|
}
|
||||||
OS << ')';
|
OS << ')';
|
||||||
|
|
|
@ -1114,18 +1114,12 @@ ObjCStringLiteral* ObjCStringLiteral::CreateImpl(Deserializer& D, ASTContext& C)
|
||||||
|
|
||||||
void BlockExpr::EmitImpl(Serializer& S) const {
|
void BlockExpr::EmitImpl(Serializer& S) const {
|
||||||
S.Emit(getType());
|
S.Emit(getType());
|
||||||
S.Emit(getCaretLocation());
|
S.EmitOwnedPtr(TheBlock);
|
||||||
S.EmitOwnedPtr(Body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockExpr* BlockExpr::CreateImpl(Deserializer& D, ASTContext& C) {
|
BlockExpr* BlockExpr::CreateImpl(Deserializer& D, ASTContext& C) {
|
||||||
QualType Q = QualType::ReadVal(D);
|
QualType T = QualType::ReadVal(D);
|
||||||
SourceLocation L = SourceLocation::ReadVal(D);
|
return new BlockExpr(cast<BlockDecl>(D.ReadOwnedPtr<Decl>(C)),T);
|
||||||
/*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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockDeclRefExpr::EmitImpl(Serializer& S) const {
|
void BlockDeclRefExpr::EmitImpl(Serializer& S) const {
|
||||||
|
|
|
@ -2931,8 +2931,11 @@ Sema::ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, StmtTy *body,
|
||||||
BSI->isVariadic);
|
BSI->isVariadic);
|
||||||
|
|
||||||
BlockTy = Context.getBlockPointerType(BlockTy);
|
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
|
/// ExprsMatchFnType - return true if the Exprs in array Args have
|
||||||
|
|
Loading…
Reference in New Issue