зеркало из https://github.com/microsoft/clang-1.git
Final phase of converting BlockDecls over to DeclContext. This is unfortunately a largish/complex diff, however it was necessry to pass all the current block tests.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57337 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
f02e9ddf5e
Коммит
090276f5e1
|
@ -990,24 +990,30 @@ protected:
|
|||
class BlockDecl : public Decl, public DeclContext {
|
||||
llvm::SmallVector<ParmVarDecl*, 8> Args;
|
||||
Stmt *Body;
|
||||
|
||||
// Since BlockDecl's aren't named/scoped, we need to store the context.
|
||||
DeclContext *ParentContext;
|
||||
protected:
|
||||
BlockDecl(DeclContext *DC, SourceLocation CaretLoc,
|
||||
ParmVarDecl **args, unsigned numargs)
|
||||
: Decl(Block, CaretLoc), DeclContext(Block),
|
||||
Args(args, args+numargs), Body(0) {}
|
||||
BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
|
||||
: Decl(Block, CaretLoc), DeclContext(Block), Body(0), ParentContext(DC) {}
|
||||
|
||||
virtual ~BlockDecl();
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
public:
|
||||
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
ParmVarDecl **args, unsigned numargs);
|
||||
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
|
||||
|
||||
SourceLocation getCaretLocation() const { return getLocation(); }
|
||||
|
||||
Stmt *getBody() const { return Body; }
|
||||
void setBody(Stmt *B) { Body = B; }
|
||||
|
||||
void setArgs(ParmVarDecl **args, unsigned numargs) {
|
||||
Args.clear();
|
||||
Args.insert(Args.begin(), args, args+numargs);
|
||||
}
|
||||
DeclContext *getParentContext() { return ParentContext; }
|
||||
|
||||
/// 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(); }
|
||||
|
@ -1016,7 +1022,7 @@ public:
|
|||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == Block; }
|
||||
static bool classof(const TranslationUnitDecl *D) { return true; }
|
||||
static bool classof(const BlockDecl *D) { return true; }
|
||||
|
||||
protected:
|
||||
/// EmitImpl - Serialize this BlockDecl. Called by Decl::Emit.
|
||||
|
|
|
@ -267,6 +267,8 @@ class DeclContext {
|
|||
static To *CastTo(const From *D) {
|
||||
Decl::Kind DK = KindTrait<From>::getKind(D);
|
||||
switch(DK) {
|
||||
case Decl::Block:
|
||||
return static_cast<BlockDecl*>(const_cast<From*>(D));
|
||||
case Decl::TranslationUnit:
|
||||
return static_cast<TranslationUnitDecl*>(const_cast<From*>(D));
|
||||
case Decl::Namespace:
|
||||
|
|
|
@ -538,8 +538,11 @@ public:
|
|||
|
||||
/// ActOnBlockStart - This callback is invoked when a block literal is
|
||||
/// started. The result pointer is passed into the block finalizers.
|
||||
virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope,
|
||||
Declarator &ParamInfo) {}
|
||||
virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {}
|
||||
|
||||
/// ActOnBlockArguments - This callback allows processing of block arguments.
|
||||
/// If there are no arguments, this is still invoked.
|
||||
virtual void ActOnBlockArguments(Declarator &ParamInfo) {}
|
||||
|
||||
/// ActOnBlockError - If there is an error parsing a block, this callback
|
||||
/// is invoked to pop the information about the block from the action impl.
|
||||
|
|
|
@ -76,10 +76,9 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
|||
TypeSpecStartLoc);
|
||||
}
|
||||
|
||||
BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
ParmVarDecl **args, unsigned numargs) {
|
||||
BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
|
||||
void *Mem = C.getAllocator().Allocate<BlockDecl>();
|
||||
return new (Mem) BlockDecl(DC, L, args, numargs);
|
||||
return new (Mem) BlockDecl(DC, L);
|
||||
}
|
||||
|
||||
FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L,
|
||||
|
|
|
@ -339,6 +339,8 @@ void Decl::Destroy(ASTContext& C) {
|
|||
DeclContext *DeclContext::getParent() const {
|
||||
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(this))
|
||||
return SD->getDeclContext();
|
||||
else if (BlockDecl *BD = dyn_cast<BlockDecl>(this))
|
||||
return BD->getParentContext();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1094,6 +1094,9 @@ Parser::ExprResult Parser::ParseBlockLiteralExpression() {
|
|||
// within or outside of the block.
|
||||
EnterScope(Scope::BlockScope|Scope::FnScope|Scope::BreakScope|
|
||||
Scope::ContinueScope|Scope::DeclScope);
|
||||
|
||||
// Inform sema that we are starting a block.
|
||||
Actions.ActOnBlockStart(CaretLoc, CurScope);
|
||||
|
||||
// Parse the return type if present.
|
||||
DeclSpec DS;
|
||||
|
@ -1119,7 +1122,7 @@ Parser::ExprResult Parser::ParseBlockLiteralExpression() {
|
|||
}
|
||||
|
||||
// Inform sema that we are starting a block.
|
||||
Actions.ActOnBlockStart(CaretLoc, CurScope, ParamInfo);
|
||||
Actions.ActOnBlockArguments(ParamInfo);
|
||||
|
||||
ExprResult Result = true;
|
||||
if (Tok.is(tok::l_brace)) {
|
||||
|
|
|
@ -575,8 +575,11 @@ public:
|
|||
|
||||
/// ActOnBlockStart - This callback is invoked when a block literal is
|
||||
/// started.
|
||||
virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope,
|
||||
Declarator &ParamInfo);
|
||||
virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
|
||||
|
||||
/// ActOnBlockArguments - This callback allows processing of block arguments.
|
||||
/// If there are no arguments, this is still invoked.
|
||||
virtual void ActOnBlockArguments(Declarator &ParamInfo);
|
||||
|
||||
/// ActOnBlockError - If there is an error parsing a block, this callback
|
||||
/// is invoked to pop the information about the block from the action impl.
|
||||
|
|
|
@ -309,34 +309,6 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
|
|||
StringToks[NumStringToks-1].getLocation());
|
||||
}
|
||||
|
||||
/// DeclDefinedWithinScope - Return true if the specified decl is defined at or
|
||||
/// within the 'Within' scope. The current Scope is CurScope.
|
||||
///
|
||||
/// FIXME: This method is extremely inefficient (linear scan), this should not
|
||||
/// be used in common cases. Replace with the more modern DeclContext. We need
|
||||
/// to make sure both assignments below produce an error.
|
||||
///
|
||||
/// int main(int argc) {
|
||||
/// int xx;
|
||||
/// ^(int X) {
|
||||
/// xx = 4; // error (variable is not assignable)
|
||||
/// argc = 3; // no error.
|
||||
/// };
|
||||
/// }
|
||||
///
|
||||
static bool DeclDefinedWithinScope(ScopedDecl *D, Scope *Within,
|
||||
Scope *CurScope) {
|
||||
while (1) {
|
||||
assert(CurScope && "CurScope not nested within 'Within'?");
|
||||
|
||||
// Check this scope for the decl.
|
||||
if (CurScope->isDeclScope(D)) return true;
|
||||
|
||||
if (CurScope == Within) return false;
|
||||
CurScope = CurScope->getParent();
|
||||
}
|
||||
}
|
||||
|
||||
/// ActOnIdentifierExpr - The parser read an identifier in expression context,
|
||||
/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
|
||||
/// identifier is used in a function call context.
|
||||
|
@ -373,17 +345,6 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
|
|||
return new PredefinedExpr(Loc, T, PredefinedExpr::ObjCSuper);
|
||||
}
|
||||
}
|
||||
// If we are parsing a block, check the block parameter list.
|
||||
if (CurBlock) {
|
||||
BlockSemaInfo *BLK = CurBlock;
|
||||
do {
|
||||
for (unsigned i = 0, e = BLK->Params.size(); i != e && D == 0; ++i)
|
||||
if (BLK->Params[i]->getIdentifier() == &II)
|
||||
D = BLK->Params[i];
|
||||
if (D)
|
||||
break; // Found!
|
||||
} while ((BLK = BLK->PrevBlockInfo)); // Look through any enclosing blocks.
|
||||
}
|
||||
if (D == 0) {
|
||||
// Otherwise, this could be an implicitly declared function reference (legal
|
||||
// in C90, extension in C99).
|
||||
|
@ -437,27 +398,26 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
|
|||
if (VD->isInvalidDecl())
|
||||
return true;
|
||||
|
||||
// If this reference is not in a block or if the referenced variable is
|
||||
// within the block, create a normal DeclRefExpr.
|
||||
//
|
||||
// FIXME: This will create BlockDeclRefExprs for global variables,
|
||||
// function references, etc which is suboptimal :) and breaks
|
||||
// things like "integer constant expression" tests.
|
||||
//
|
||||
if (!CurBlock || DeclDefinedWithinScope(VD, CurBlock->TheScope, S) ||
|
||||
isa<EnumConstantDecl>(VD) || isa<ParmVarDecl>(VD))
|
||||
return new DeclRefExpr(VD, VD->getType(), Loc);
|
||||
|
||||
// If we are in a block and the variable is outside the current block,
|
||||
// bind the variable reference with a BlockDeclRefExpr.
|
||||
|
||||
// The BlocksAttr indicates the variable is bound by-reference.
|
||||
if (VD->getAttr<BlocksAttr>())
|
||||
return new BlockDeclRefExpr(VD, VD->getType(), Loc, true);
|
||||
if (CurBlock && (CurBlock->TheDecl != VD->getDeclContext()) &&
|
||||
!isa<EnumConstantDecl>(VD)) {
|
||||
// If we are in a block and the variable is outside the current block,
|
||||
// bind the variable reference with a BlockDeclRefExpr.
|
||||
|
||||
// Variable will be bound by-copy, make it const within the closure.
|
||||
VD->getType().addConst();
|
||||
return new BlockDeclRefExpr(VD, VD->getType(), Loc, false);
|
||||
// The BlocksAttr indicates the variable is bound by-reference.
|
||||
if (VD->getAttr<BlocksAttr>())
|
||||
return new BlockDeclRefExpr(VD, VD->getType(), Loc, true);
|
||||
|
||||
// Variable will be bound by-copy, make it const within the closure.
|
||||
VD->getType().addConst();
|
||||
return new BlockDeclRefExpr(VD, VD->getType(), Loc, false);
|
||||
}
|
||||
// If this reference is not in a block or if the referenced variable is
|
||||
// within the block, create a normal DeclRefExpr.
|
||||
return new DeclRefExpr(VD, VD->getType(), Loc);
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
|
||||
|
@ -2856,8 +2816,7 @@ Sema::ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// ActOnBlockStart - This callback is invoked when a block literal is started.
|
||||
void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope,
|
||||
Declarator &ParamInfo) {
|
||||
void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
|
||||
// Analyze block parameters.
|
||||
BlockSemaInfo *BSI = new BlockSemaInfo();
|
||||
|
||||
|
@ -2868,13 +2827,18 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope,
|
|||
BSI->ReturnType = 0;
|
||||
BSI->TheScope = BlockScope;
|
||||
|
||||
BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc);
|
||||
PushDeclContext(BSI->TheDecl);
|
||||
}
|
||||
|
||||
void Sema::ActOnBlockArguments(Declarator &ParamInfo) {
|
||||
// Analyze arguments to block.
|
||||
assert(ParamInfo.getTypeObject(0).Kind == DeclaratorChunk::Function &&
|
||||
"Not a function declarator!");
|
||||
DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getTypeObject(0).Fun;
|
||||
|
||||
BSI->hasPrototype = FTI.hasPrototype;
|
||||
BSI->isVariadic = true;
|
||||
CurBlock->hasPrototype = FTI.hasPrototype;
|
||||
CurBlock->isVariadic = true;
|
||||
|
||||
// Check for C99 6.7.5.3p10 - foo(void) is a non-varargs function that takes
|
||||
// no arguments, not a function that takes a single void argument.
|
||||
|
@ -2883,14 +2847,19 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope,
|
|||
(!((ParmVarDecl *)FTI.ArgInfo[0].Param)->getType().getCVRQualifiers() &&
|
||||
((ParmVarDecl *)FTI.ArgInfo[0].Param)->getType()->isVoidType())) {
|
||||
// empty arg list, don't push any params.
|
||||
BSI->isVariadic = false;
|
||||
CurBlock->isVariadic = false;
|
||||
} else if (FTI.hasPrototype) {
|
||||
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
|
||||
BSI->Params.push_back((ParmVarDecl *)FTI.ArgInfo[i].Param);
|
||||
BSI->isVariadic = FTI.isVariadic;
|
||||
CurBlock->Params.push_back((ParmVarDecl *)FTI.ArgInfo[i].Param);
|
||||
CurBlock->isVariadic = FTI.isVariadic;
|
||||
}
|
||||
BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc,
|
||||
&BSI->Params[0], BSI->Params.size());
|
||||
CurBlock->TheDecl->setArgs(&CurBlock->Params[0], CurBlock->Params.size());
|
||||
|
||||
for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
|
||||
E = CurBlock->TheDecl->param_end(); AI != E; ++AI)
|
||||
// If this has an identifier, add it to the scope stack.
|
||||
if ((*AI)->getIdentifier())
|
||||
PushOnScopeChains(*AI, CurBlock->TheScope);
|
||||
}
|
||||
|
||||
/// ActOnBlockError - If there is an error parsing a block, this callback
|
||||
|
@ -2914,6 +2883,8 @@ Sema::ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, StmtTy *body,
|
|||
llvm::OwningPtr<BlockSemaInfo> BSI(CurBlock);
|
||||
llvm::OwningPtr<CompoundStmt> Body(static_cast<CompoundStmt*>(body));
|
||||
|
||||
PopDeclContext();
|
||||
|
||||
// Pop off CurBlock, handle nested blocks.
|
||||
CurBlock = CurBlock->PrevBlockInfo;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче