this patch accomodates clattner's comments on expression processing in @try-statement.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42611 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseExpr.cpp b/Parse/ParseExpr.cpp
index 4608898..1b261aa 100644
--- a/Parse/ParseExpr.cpp
+++ b/Parse/ParseExpr.cpp
@@ -177,7 +177,7 @@
 /// routine is necessary to disambiguate @try-statement from,
 /// for example, @encode-expression.
 ///
-Parser::ExprResult Parser::ParseExpressionWithLeadingAt(SourceLocation &AtLoc) {
+Parser::ExprResult Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {
   ExprResult LHS = ParseObjCExpression(AtLoc);
   if (LHS.isInvalid) return LHS;
  
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
index c557687..dff6e0c 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -1067,10 +1067,10 @@
 ///  objc-throw-statement:
 ///    throw expression[opt];
 ///
-Parser::DeclTy *Parser::ParseObjCThrowStmt(SourceLocation &atLoc) {
+Parser::DeclTy *Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
   ConsumeToken(); // consume throw
   if (Tok.getKind() != tok::semi) {
-    ExprResult Res = ParseAssignmentExpression();
+    ExprResult Res = ParseExpression();
     if (Res.isInvalid) {
       SkipUntil(tok::semi);
       return 0;
@@ -1090,7 +1090,7 @@
 ///     parameter-declaration
 ///     '...' [OBJC2]
 ///
-Parser::DeclTy *Parser::ParseObjCTryStmt(SourceLocation &atLoc) {
+Parser::DeclTy *Parser::ParseObjCTryStmt(SourceLocation atLoc) {
   bool catch_or_finally_seen = false;
   ConsumeToken(); // consume try
   if (Tok.getKind() != tok::l_brace) {
@@ -1172,21 +1172,21 @@
   StmtResult FnBody = ParseCompoundStatementBody();
 }
 
-Parser::ExprResult Parser::ParseObjCExpression(SourceLocation &AtLoc) {
+Parser::ExprResult Parser::ParseObjCExpression(SourceLocation AtLoc) {
 
   switch (Tok.getKind()) {
     case tok::string_literal:    // primary-expression: string-literal
     case tok::wide_string_literal:
-      return ParseObjCStringLiteral();
+      return ParsePostfixExpressionSuffix(ParseObjCStringLiteral());
     default:
       break;
   }
   
   switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
     case tok::objc_encode:
-      return ParseObjCEncodeExpression();
+      return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression());
     case tok::objc_protocol:
-      return ParseObjCProtocolExpression();
+      return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression());
     default:
       Diag(AtLoc, diag::err_unexpected_at);
       SkipUntil(tok::semi);
diff --git a/Parse/ParseStmt.cpp b/Parse/ParseStmt.cpp
index d37973b..7dc6a62 100644
--- a/Parse/ParseStmt.cpp
+++ b/Parse/ParseStmt.cpp
@@ -34,8 +34,8 @@
 ///         selection-statement
 ///         iteration-statement
 ///         jump-statement
-/// [OBC]   objc-throw-statement         [TODO]
-/// [OBC]   objc-try-catch-statement     [TODO]
+/// [OBC]   objc-throw-statement
+/// [OBC]   objc-try-catch-statement
 /// [OBC]   objc-synchronized-statement  [TODO]
 /// [GNU]   asm-statement
 /// [OMP]   openmp-construct             [TODO]
@@ -64,9 +64,9 @@
 ///         'return' expression[opt] ';'
 /// [GNU]   'goto' '*' expression ';'
 ///
-/// [OBC] objc-throw-statement:           [TODO]
-/// [OBC]   '@' 'throw' expression ';'    [TODO]
-/// [OBC]   '@' 'throw' ';'               [TODO]
+/// [OBC] objc-throw-statement:
+/// [OBC]   '@' 'throw' expression ';'
+/// [OBC]   '@' 'throw' ';' 
 /// 
 Parser::StmtResult Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
   const char *SemiError = 0;
@@ -91,19 +91,28 @@
         return ParseObjCTryStmt(AtLoc);
       else if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_throw)
         return ParseObjCThrowStmt(AtLoc);
+      ExprResult Res = ParseExpressionWithLeadingAt(AtLoc);
+      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
+        // ParseExpression does not consume any tokens.
+        SkipUntil(tok::semi);
+        return true;
+      }
+      // Otherwise, eat the semicolon.
+      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
+      return Actions.ActOnExprStmt(Res.Val);
     }
-    // Fall thru.
 
   default:
-    if (Kind != tok::at && !OnlyStatement && isDeclarationSpecifier()) {
+    if (!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 = (Kind == tok::at) ? ParseExpressionWithLeadingAt(AtLoc) 
-				         : ParseExpression();
+      ExprResult Res = 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