[cfe-commits] r42148 - in /cfe/trunk: Parse/ParseExpr.cpp Parse/ParseObjc.cpp Parse/ParseStmt.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Parser.h test/Parser/objc-try-catch-1.m
Fariborz Jahanian
fjahanian at apple.com
Wed Sep 19 12:14:33 PDT 2007
Author: fjahanian
Date: Wed Sep 19 14:14:32 2007
New Revision: 42148
URL: http://llvm.org/viewvc/llvm-project?rev=42148&view=rev
Log:
Patch to parse objective-c's @try-statement and @throw-statement.
Added:
cfe/trunk/test/Parser/objc-try-catch-1.m
Modified:
cfe/trunk/Parse/ParseExpr.cpp
cfe/trunk/Parse/ParseObjc.cpp
cfe/trunk/Parse/ParseStmt.cpp
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/include/clang/Parse/Parser.h
Modified: cfe/trunk/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseExpr.cpp?rev=42148&r1=42147&r2=42148&view=diff
==============================================================================
--- cfe/trunk/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/Parse/ParseExpr.cpp Wed Sep 19 14:14:32 2007
@@ -172,6 +172,18 @@
return ParseRHSOfBinaryExpression(LHS, prec::Comma);
}
+/// This routine is called when the '@' is seen and consumed.
+/// Current token is an Identifier and is not a 'try'. This
+/// routine is necessary to disambiguate @try-statement from
+/// ,for example, @encode-expression.
+///
+Parser::ExprResult Parser::ParseExpressionWithLeadingAt(SourceLocation &AtLoc) {
+ ExprResult LHS = ParseObjCExpression(AtLoc);
+ if (LHS.isInvalid) return LHS;
+
+ return ParseRHSOfBinaryExpression(LHS, prec::Comma);
+}
+
/// ParseAssignmentExpression - Parse an expr that doesn't include commas.
///
Parser::ExprResult Parser::ParseAssignmentExpression() {
@@ -589,7 +601,10 @@
case tok::kw_static_cast:
return ParseCXXCasts();
case tok::at:
- return ParseObjCExpression();
+ {
+ SourceLocation AtLoc = ConsumeToken();
+ return ParseObjCExpression(AtLoc);
+ }
case tok::l_square:
return ParseObjCMessageExpression ();
default:
Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=42148&r1=42147&r2=42148&view=diff
==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Wed Sep 19 14:14:32 2007
@@ -916,6 +916,77 @@
Diag(Tok, diag::err_expected_semi_after, "@dynamic");
return 0;
}
+
+/// objc-throw-statement:
+/// throw expression[opt];
+///
+Parser::DeclTy *Parser::ParseObjCThrowStmt(SourceLocation &atLoc) {
+ ConsumeToken(); // consume throw
+ if (Tok.getKind() != tok::semi) {
+ ExprResult Res = ParseAssignmentExpression();
+ if (Res.isInvalid) {
+ SkipUntil(tok::semi);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/// objc-try-catch-statement:
+/// @try compound-statement objc-catch-list[opt]
+/// @try compound-statement objc-catch-list[opt] @finally compound-statement
+///
+/// objc-catch-list:
+/// @catch ( parameter-declaration ) compound-statement
+/// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
+/// catch-parameter-declaration:
+/// parameter-declaration
+/// '...' [OBJC2]
+///
+Parser::DeclTy *Parser::ParseObjCTryStmt(SourceLocation &atLoc) {
+ bool catch_or_finally_seen = false;
+ ConsumeToken(); // consume try
+ if (Tok.getKind() != tok::l_brace) {
+ Diag (Tok, diag::err_expected_lbrace);
+ return 0;
+ }
+ StmtResult TryBody = ParseCompoundStatementBody();
+ while (Tok.getKind() == tok::at) {
+ ConsumeToken();
+ if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_catch) {
+ SourceLocation catchLoc = ConsumeToken(); // consume catch
+ if (Tok.getKind() == tok::l_paren) {
+ ConsumeParen();
+ if (Tok.getKind() != tok::ellipsis) {
+ DeclSpec DS;
+ ParseDeclarationSpecifiers(DS);
+ // Parse the parameter-declaration.
+ // FIXME: BlockContext may not be the right context!
+ Declarator ParmDecl(DS, Declarator::BlockContext);
+ ParseDeclarator(ParmDecl);
+ }
+ else
+ ConsumeToken(); // consume '...'
+ ConsumeParen();
+ StmtResult CatchMody = ParseCompoundStatementBody();
+ }
+ else {
+ Diag(catchLoc, diag::err_expected_lparen_after, "@catch clause");
+ return 0;
+ }
+ catch_or_finally_seen = true;
+ }
+ else if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_finally) {
+ ConsumeToken(); // consume finally
+ StmtResult FinallyBody = ParseCompoundStatementBody();
+ catch_or_finally_seen = true;
+ break;
+ }
+ }
+ if (!catch_or_finally_seen)
+ Diag(atLoc, diag::err_missing_catch_finally);
+ return 0;
+}
/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
///
@@ -954,8 +1025,7 @@
StmtResult FnBody = ParseCompoundStatementBody();
}
-Parser::ExprResult Parser::ParseObjCExpression() {
- SourceLocation AtLoc = ConsumeToken(); // the "@"
+Parser::ExprResult Parser::ParseObjCExpression(SourceLocation &AtLoc) {
switch (Tok.getKind()) {
case tok::string_literal: // primary-expression: string-literal
Modified: cfe/trunk/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseStmt.cpp?rev=42148&r1=42147&r2=42148&view=diff
==============================================================================
--- cfe/trunk/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/Parse/ParseStmt.cpp Wed Sep 19 14:14:32 2007
@@ -75,22 +75,35 @@
// Cases in this switch statement should fall through if the parser expects
// the token to end in a semicolon (in which case SemiError should be set),
// or they directly 'return;' if not.
- switch (Tok.getKind()) {
+ tok::TokenKind Kind = Tok.getKind();
+ SourceLocation AtLoc;
+ switch (Kind) {
case tok::identifier: // C99 6.8.1: labeled-statement
// identifier ':' statement
// declaration (if !OnlyStatement)
// expression[opt] ';'
return ParseIdentifierStatement(OnlyStatement);
+ case tok::at: // May be a @try or @throw statement
+ {
+ AtLoc = ConsumeToken(); // consume @
+ if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_try)
+ return ParseObjCTryStmt(AtLoc);
+ else if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_throw)
+ return ParseObjCThrowStmt(AtLoc);
+ }
+ // Fall thru.
+
default:
- if (!OnlyStatement && isDeclarationSpecifier()) {
+ if (Kind != tok::at && !OnlyStatement && isDeclarationSpecifier()) {
return Actions.ActOnDeclStmt(ParseDeclaration(Declarator::BlockContext));
} else if (Tok.getKind() == tok::r_brace) {
Diag(Tok, diag::err_expected_statement);
return true;
} else {
// expression[opt] ';'
- ExprResult Res = ParseExpression();
+ ExprResult Res = (Kind == tok::at) ? ParseExpressionWithLeadingAt(AtLoc)
+ : ParseExpression();
if (Res.isInvalid) {
// If the expression is invalid, skip ahead to the next semicolon. Not
// doing this opens us up to the possibility of infinite loops if
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=42148&r1=42147&r2=42148&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Sep 19 14:14:32 2007
@@ -406,6 +406,8 @@
"@required may be specified in protocols only")
DIAG(err_objc_protocol_optional, ERROR,
"@optional may be specified in protocols only")
+DIAG(err_missing_catch_finally, ERROR,
+ "@try statment without a @catch and @finally clause")
//===----------------------------------------------------------------------===//
// Semantic Analysis
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=42148&r1=42147&r2=42148&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Sep 19 14:14:32 2007
@@ -270,6 +270,8 @@
DeclTy *ParseObjCAtAliasDeclaration(SourceLocation atLoc);
DeclTy *ParseObjCPropertySynthesize(SourceLocation atLoc);
DeclTy *ParseObjCPropertyDynamic(SourceLocation atLoc);
+ DeclTy *ParseObjCTryStmt(SourceLocation &atLoc);
+ DeclTy *ParseObjCThrowStmt(SourceLocation &atLoc);
IdentifierInfo *ParseObjCSelector();
// Definitions for Objective-c context sensitive keywords recognition.
@@ -310,6 +312,7 @@
ExprResult ParseAssignmentExpression(); // Expr that doesn't include commas.
ExprResult ParseExpressionWithLeadingIdentifier(const Token &Tok);
+ ExprResult ParseExpressionWithLeadingAt(SourceLocation &AtLoc);
ExprResult ParseAssignmentExprWithLeadingIdentifier(const Token &Tok);
ExprResult ParseAssignmentExpressionWithLeadingStar(const Token &Tok);
@@ -355,7 +358,7 @@
//===--------------------------------------------------------------------===//
// Objective-C Expressions
- ExprResult ParseObjCExpression();
+ ExprResult ParseObjCExpression(SourceLocation &AtLocation);
ExprResult ParseObjCStringLiteral();
ExprResult ParseObjCEncodeExpression();
ExprResult ParseObjCProtocolExpression();
Added: cfe/trunk/test/Parser/objc-try-catch-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objc-try-catch-1.m?rev=42148&view=auto
==============================================================================
--- cfe/trunk/test/Parser/objc-try-catch-1.m (added)
+++ cfe/trunk/test/Parser/objc-try-catch-1.m Wed Sep 19 14:14:32 2007
@@ -0,0 +1,36 @@
+void * proc();
+
+ at interface Frob
+ at end
+
+ at interface Frob1
+ at end
+
+void * foo()
+{
+ @try {
+ return proc();
+ }
+ @catch (Frob* ex) {
+ @throw;
+ }
+ @catch (Frob1* ex) {
+ @throw proc();
+ }
+ @finally {
+ @try {
+ return proc();
+ }
+ @catch (Frob* ex) {
+ @throw;
+ }
+ @catch(...) {
+ @throw (4,3,proc());
+ }
+ }
+
+ @try { // expected-error {{@try statment without a @catch and @finally clause}}
+ return proc();
+ }
+}
+
More information about the cfe-commits
mailing list