[cfe-commits] r55495 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Action.h include/clang/Parse/DeclSpec.h include/clang/Parse/Parser.h include/clang/Parse/Scope.h lib/AST/ASTContext.cpp lib/Parse/ParseExpr.cpp test/Parser/block-pointer-decl.c
Steve Naroff
snaroff at apple.com
Thu Aug 28 12:20:44 PDT 2008
Author: snaroff
Date: Thu Aug 28 14:20:44 2008
New Revision: 55495
URL: http://llvm.org/viewvc/llvm-project?rev=55495&view=rev
Log:
Add parser/action support for block literal expressions.
Parser support for blocks is almost complete...just need to add support for the __block() storage class qualifier.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/DeclSpec.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Parse/Scope.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/test/Parser/block-pointer-decl.c
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=55495&r1=55494&r2=55495&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Thu Aug 28 14:20:44 2008
@@ -1116,6 +1116,10 @@
// CHECK: use of uninitialized values
DIAG(warn_uninit_val, WARNING, "use of uninitialized variable")
+// Blocks
+DIAG(err_expected_block_lbrace, ERROR,
+ "expected '{' in block literal")
+
// CFString checking
DIAG(err_cfstring_literal_not_string_constant, ERROR,
"CFString literal is not a string constant")
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=55495&r1=55494&r2=55495&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Thu Aug 28 14:20:44 2008
@@ -533,6 +533,27 @@
return 0;
}
+ //===------------------------- "Block" Extension ------------------------===//
+
+ /// 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) {}
+
+ /// ActOnBlockError - If there is an error parsing a block, this callback
+ /// is invoked to pop the information about the block from the action impl.
+ virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {}
+
+ /// ActOnBlockStmtExpr - This is called when the body of a block statement
+ /// literal was successfully completed. ^(int x){...}
+ virtual ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, StmtTy *Body,
+ Scope *CurScope) { return 0; }
+
+ /// ActOnBlockExprExpr - This is called when the body of a block
+ /// expression literal was successfully completed. ^(int x)[foo bar: x]
+ virtual ExprResult ActOnBlockExprExpr(SourceLocation CaretLoc, ExprTy *Body,
+ Scope *CurScope) { return 0; }
+
//===------------------------- C++ Declarations -------------------------===//
/// ActOnStartNamespaceDef - This is called at the start of a namespace
Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=55495&r1=55494&r2=55495&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Thu Aug 28 14:20:44 2008
@@ -481,6 +481,7 @@
case Reference: return Ref.AttrList;
case Array: return 0;
case Function: return 0;
+ case BlockPointer: return 0; // FIXME: Do blocks have attr list?
}
}
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=55495&r1=55494&r2=55495&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Aug 28 14:20:44 2008
@@ -442,6 +442,11 @@
ExprResult ParseInitializerWithPotentialDesignator();
//===--------------------------------------------------------------------===//
+ // clang Expressions
+
+ ExprResult ParseBlockLiteralExpression(); // ^{...}
+
+ //===--------------------------------------------------------------------===//
// Objective-C Expressions
bool isTokObjCMessageIdentifierReceiver() const {
Modified: cfe/trunk/include/clang/Parse/Scope.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Scope.h?rev=55495&r1=55494&r2=55495&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Scope.h (original)
+++ cfe/trunk/include/clang/Parse/Scope.h Thu Aug 28 14:20:44 2008
@@ -45,7 +45,13 @@
DeclScope = 0x08,
/// CXXClassScope - The scope of a C++ struct/union/class definition.
- CXXClassScope = 0x10
+ CXXClassScope = 0x10,
+
+ /// BlockScope - This is a scope that corresponds to a block object.
+ /// Blocks serve as top-level scopes for some objects like labels, they
+ /// also prevent things like break and continue. BlockScopes have the
+ /// other flags set as well.
+ BlockScope = 0x20
};
private:
/// The parent scope for this scope. This is null for the translation-unit
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=55495&r1=55494&r2=55495&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Aug 28 14:20:44 2008
@@ -613,8 +613,8 @@
/// getBlockPointerType - Return the uniqued reference to the type for
/// a pointer to the specified block.
QualType ASTContext::getBlockPointerType(QualType T) {
- assert(T->isFunctionType() && "closure of function types only");
- // Unique pointers, to guarantee there is only one closure of a particular
+ assert(T->isFunctionType() && "block of function types only");
+ // Unique pointers, to guarantee there is only one block of a particular
// structure.
llvm::FoldingSetNodeID ID;
BlockPointerType::Profile(ID, T);
@@ -624,7 +624,7 @@
BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(PT, 0);
- // If the closure pointee type isn't canonical, this won't be a canonical
+ // If the block pointee type isn't canonical, this won't be a canonical
// type either so fill in the canonical type field.
QualType Canonical;
if (!T->isCanonical()) {
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=55495&r1=55494&r2=55495&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Aug 28 14:20:44 2008
@@ -21,6 +21,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Scope.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallString.h"
@@ -380,6 +381,7 @@
/// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
/// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
/// [C++] 'this' [C++ 9.3.2]
+/// [clang] '^' block-literal
///
/// constant: [C99 6.4.4]
/// integer-constant
@@ -595,6 +597,11 @@
if (getLang().ObjC1)
return ParsePostfixExpressionSuffix(ParseObjCMessageExpression());
// FALL THROUGH.
+ case tok::caret:
+ if (getLang().Blocks)
+ return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
+ Diag(Tok, diag::err_expected_expression);
+ return ExprResult(true);
default:
UnhandledToken:
Diag(Tok, diag::err_expected_expression);
@@ -1068,3 +1075,74 @@
CommaLocs.push_back(ConsumeToken());
}
}
+
+/// ParseBlockLiteralExpression - Parse a block literal, which roughly looks
+/// like ^(int x){ return x+1; } or ^(int y)foo(4, y, z)
+///
+/// block-literal:
+/// [clang] '^' block-args[opt] compound-statement
+/// [clang] '^' block-args cast-expression
+/// [clang] block-args:
+/// [clang] '(' parameter-list ')'
+///
+Parser::ExprResult Parser::ParseBlockLiteralExpression() {
+ assert(Tok.is(tok::caret) && "block literal starts with ^");
+ SourceLocation CaretLoc = ConsumeToken();
+
+ // Enter a scope to hold everything within the block. This includes the
+ // argument decls, decls within the compound expression, etc. This also
+ // allows determining whether a variable reference inside the block is
+ // within or outside of the block.
+ EnterScope(Scope::BlockScope|Scope::FnScope|Scope::BreakScope|
+ Scope::ContinueScope|Scope::DeclScope);
+
+ // Parse the return type if present.
+ DeclSpec DS;
+ Declarator ParamInfo(DS, Declarator::PrototypeContext);
+
+ // If this block has arguments, parse them. There is no ambiguity here with
+ // the expression case, because the expression case requires a parameter list.
+ if (Tok.is(tok::l_paren)) {
+ ParseParenDeclarator(ParamInfo);
+ // Parse the pieces after the identifier as if we had "int(...)".
+ ParamInfo.SetIdentifier(0, CaretLoc);
+ if (ParamInfo.getInvalidType()) {
+ // If there was an error parsing the arguments, they may have tried to use
+ // ^(x+y) which requires an argument list. Just skip the whole block
+ // literal.
+ ExitScope();
+ return true;
+ }
+ } else {
+ // Otherwise, pretend we saw (void).
+ ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
+ 0, 0, CaretLoc));
+ }
+
+ // Inform sema that we are starting a block.
+ Actions.ActOnBlockStart(CaretLoc, CurScope, ParamInfo);
+
+ ExprResult Result;
+ if (Tok.is(tok::l_brace)) {
+ StmtResult Stmt = ParseCompoundStatementBody();
+ if (!Stmt.isInvalid) {
+ Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.Val, CurScope);
+ } else {
+ Actions.ActOnBlockError(CaretLoc, CurScope);
+ Result = true;
+ }
+ } else {
+ ExprResult Expr = ParseCastExpression(false);
+ if (!Expr.isInvalid) {
+ Result = Actions.ActOnBlockExprExpr(CaretLoc, Expr.Val, CurScope);
+ } else {
+ Actions.ActOnBlockError(CaretLoc, CurScope);
+ Diag(Tok, diag::err_expected_block_lbrace);
+ Result = true;
+ }
+ }
+
+ ExitScope();
+ return Result;
+}
+
Modified: cfe/trunk/test/Parser/block-pointer-decl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/block-pointer-decl.c?rev=55495&r1=55494&r2=55495&view=diff
==============================================================================
--- cfe/trunk/test/Parser/block-pointer-decl.c (original)
+++ cfe/trunk/test/Parser/block-pointer-decl.c Thu Aug 28 14:20:44 2008
@@ -7,12 +7,20 @@
int blockTaker (int (^myBlock)(int), int other_input)
{
- return 0;
+ return 5 * myBlock (other_input);
}
int main (int argc, char **argv)
{
- int (^blockptr) (int);
+ int (^blockptr) (int) = ^(int inval) {
+ printf ("Inputs: %d, %d.\n", argc, inval);
+ return argc * inval;
+ };
+
+
+ argc = 10;
+ printf ("I got: %d.\n",
+ blockTaker (blockptr, 6));
return 0;
}
More information about the cfe-commits
mailing list