]> granicus.if.org Git - clang/commitdiff
Fix Parser::ParseObjCTryStmt() to allow for trailing @-keyword statements/expressions.
authorSteve Naroff <snaroff@apple.com>
Tue, 5 Feb 2008 21:27:35 +0000 (21:27 +0000)
committerSteve Naroff <snaroff@apple.com>
Tue, 5 Feb 2008 21:27:35 +0000 (21:27 +0000)
This bug fix is the result of not having 2-token lookahead to recognize specific @-keywords.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46768 91177308-0d34-0410-b5e6-96231b3b80d8

Parse/ParseObjc.cpp
Parse/ParseStmt.cpp
include/clang/Parse/Parser.h
test/Parser/objc-try-catch-1.m

index 663fa98aa254ed5b0cd6cafe1636af8f03278078..890b9bcaf9a4aea36ac70235ffbb96ebf50067af 100644 (file)
@@ -1150,8 +1150,11 @@ Parser::StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
 ///     parameter-declaration
 ///     '...' [OBJC2]
 ///
-Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
+Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc, 
+                                            bool &processAtKeyword) {
   bool catch_or_finally_seen = false;
+  processAtKeyword = false;
+  
   ConsumeToken(); // consume try
   if (Tok.isNot(tok::l_brace)) {
     Diag (Tok, diag::err_expected_lbrace);
@@ -1180,8 +1183,7 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
                                                            DeclaratorInfo, 0);
           StmtResult stmtResult = Actions.ActOnDeclStmt(aBlockVarDecl);
           FirstPart = stmtResult.isInvalid ? 0 : stmtResult.Val;
-        }
-        else
+        } else
           ConsumeToken(); // consume '...'
         SourceLocation RParenLoc = ConsumeParen();
         StmtResult CatchBody = ParseCompoundStatementBody();
@@ -1190,16 +1192,14 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
         CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, RParenLoc, 
           FirstPart, CatchBody.Val, CatchStmts.Val);
         ExitScope();
-      }
-      else {
+      } else {
         Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after, 
              "@catch clause");
         return true;
       }
       catch_or_finally_seen = true;
-    }
-    else if (Tok.isObjCAtKeyword(tok::objc_finally)) {
-       ConsumeToken(); // consume finally
+    } else if (Tok.isObjCAtKeyword(tok::objc_finally)) {
+      ConsumeToken(); // consume finally
       StmtResult FinallyBody = ParseCompoundStatementBody();
       if (FinallyBody.isInvalid)
         FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
@@ -1207,6 +1207,9 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
                                                    FinallyBody.Val);
       catch_or_finally_seen = true;
       break;
+    } else {
+      processAtKeyword = true;
+      break;
     }
   }
   if (!catch_or_finally_seen) {
@@ -1259,6 +1262,31 @@ Parser::DeclTy *Parser::ParseObjCMethodDefinition() {
   return MDecl;
 }
 
+Parser::StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
+  if (Tok.isObjCAtKeyword(tok::objc_try)) {
+    bool parsedAtSign;
+    
+    StmtResult Res = ParseObjCTryStmt(AtLoc, parsedAtSign);
+    if (!Res.isInvalid && parsedAtSign)
+      return ParseObjCAtStatement(AtLoc);
+    return Res;
+  } else if (Tok.isObjCAtKeyword(tok::objc_throw))
+    return ParseObjCThrowStmt(AtLoc);
+  else if (Tok.isObjCAtKeyword(tok::objc_synchronized))
+    return ParseObjCSynchronizedStmt(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);
+}
+
 Parser::ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
 
   switch (Tok.getKind()) {
index 8559a3dd48ae123e708d38c91af89d9bda90f34c..b6cd558b0432c0b0b0b70a846c98ef784aa2635e 100644 (file)
@@ -87,23 +87,7 @@ Parser::StmtResult Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
   case tok::at: // May be a @try or @throw statement
     {
       AtLoc = ConsumeToken();  // consume @
-      if (Tok.isObjCAtKeyword(tok::objc_try))
-        return ParseObjCTryStmt(AtLoc);
-      else if (Tok.isObjCAtKeyword(tok::objc_throw))
-        return ParseObjCThrowStmt(AtLoc);
-      else if (Tok.isObjCAtKeyword(tok::objc_synchronized))
-        return ParseObjCSynchronizedStmt(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);
+      return ParseObjCAtStatement(AtLoc);
     }
 
   default:
index 6c3bbcddb2efa14f3b2c642a9c4f4ff47d093682..2dbae31339200dab85a2f94e33b2d2bc22742955 100644 (file)
@@ -403,7 +403,8 @@ private:
   StmtResult ParseBreakStatement();
   StmtResult ParseReturnStatement();
   StmtResult ParseAsmStatement();
-  StmtResult ParseObjCTryStmt(SourceLocation atLoc);
+  StmtResult ParseObjCAtStatement(SourceLocation atLoc);
+  StmtResult ParseObjCTryStmt(SourceLocation atLoc, bool &processAtKeyword);
   StmtResult ParseObjCThrowStmt(SourceLocation atLoc);
   StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
   void ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
index d6ad8d38ef7130685d92029413080f5c92fde304..95ca5a18f4207d37c705037fc33923f9347f661f 100644 (file)
@@ -50,3 +50,13 @@ void baz()
   @finally {}
 }
 
+void noTwoTokenLookAheadRequiresABitOfFancyFootworkInTheParser() {
+    @try {
+        // Do something
+    } @catch (...) {}
+    @try {
+        // Do something
+    } @catch (...) {}
+    return 0;
+}
+