diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 5 | ||||
-rw-r--r-- | clang/lib/AST/DeclBase.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 99 |
5 files changed, 48 insertions, 70 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index fe2e95d1579..382b9ebd512 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -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, diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index b42950ffc0b..198bc4a19ec 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -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; } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index c8d95cf053c..d0f5eb26076 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -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)) { diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 0600ae14243..6ad65e5ba3a 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -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. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index cdba6ec6ea6..a6197dd2b75 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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; |