[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