Fix Parser::ParseObjCTryStmt() to allow for trailing @-keyword statements/expressions.

This bug fix is the result of not having 2-token lookahead to recognize specific @-keywords.

llvm-svn: 46768
This commit is contained in:
Steve Naroff 2008-02-05 21:27:35 +00:00
parent a838141957
commit e6016798bf
4 changed files with 49 additions and 26 deletions

View 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()) {

View 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:

View 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,

View File

@ -50,3 +50,13 @@ void baz()
@finally {}
}
void noTwoTokenLookAheadRequiresABitOfFancyFootworkInTheParser() {
@try {
// Do something
} @catch (...) {}
@try {
// Do something
} @catch (...) {}
return 0;
}