C++: handle @try statements in the parser.

No semantic analysis yet, but this prevents the parser from generating
bogus diagnostics.

Task-number: QTCREATORBUG-9309
Change-Id: I2ec575a8474cd51bfa97b17678d3da71ab8dcd7a
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
Erik Verbruggen
2013-07-18 10:04:28 +02:00
parent 61367fc6ab
commit 23085895d6
3 changed files with 106 additions and 0 deletions

View File

@@ -333,6 +333,7 @@ bool Parser::skipUntilStatement()
case T_USING: case T_USING:
return true; return true;
case T_AT_TRY:
case T_AT_SYNCHRONIZED: case T_AT_SYNCHRONIZED:
if (objCEnabled()) if (objCEnabled())
return true; return true;
@@ -3106,6 +3107,9 @@ bool Parser::parseStatement(StatementAST *&node)
return true; return true;
} }
case T_AT_TRY:
return objCEnabled() && parseObjCTryStatement(node);
case T_AT_SYNCHRONIZED: case T_AT_SYNCHRONIZED:
return objCEnabled() && parseObjCSynchronizedStatement(node); return objCEnabled() && parseObjCSynchronizedStatement(node);
@@ -4404,6 +4408,50 @@ bool Parser::parseObjCStringLiteral(ExpressionAST *&node)
return true; return true;
} }
/// 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]
///
bool Parser::parseObjCTryStatement(StatementAST *& /*node*/)
{
DEBUG_THIS_RULE();
if (LA() != T_AT_TRY)
return false;
/*try_token =*/ consumeToken();
StatementAST *body_statment;
parseCompoundStatement(body_statment);
while (LA() == T_AT_CATCH) {
/*catch_token =*/ consumeToken();
unsigned lparen_token;
match(T_LPAREN, &lparen_token);
if (LA() == T_DOT_DOT_DOT) {
/*unsigned ellipsis_token =*/ consumeToken();
} else {
ParameterDeclarationAST *exception_decl;
parseParameterDeclaration(exception_decl);
}
unsigned rparen_token;
match(T_RPAREN, &rparen_token);
StatementAST *catch_statement;
parseCompoundStatement(catch_statement);
}
if (LA() == T_AT_FINALLY) {
StatementAST *finally_statement;
parseCompoundStatement(finally_statement);
}
return true;
}
bool Parser::parseObjCSynchronizedStatement(StatementAST *&node) bool Parser::parseObjCSynchronizedStatement(StatementAST *&node)
{ {
DEBUG_THIS_RULE(); DEBUG_THIS_RULE();

View File

@@ -222,6 +222,7 @@ public:
bool parseObjCProtocol(DeclarationAST *&node, bool parseObjCProtocol(DeclarationAST *&node,
SpecifierListAST *attributes = 0); SpecifierListAST *attributes = 0);
bool parseObjCTryStatement(StatementAST *&node);
bool parseObjCSynchronizedStatement(StatementAST *&node); bool parseObjCSynchronizedStatement(StatementAST *&node);
bool parseObjCEncodeExpression(ExpressionAST *&node); bool parseObjCEncodeExpression(ExpressionAST *&node);
bool parseObjCProtocolExpression(ExpressionAST *&node); bool parseObjCProtocolExpression(ExpressionAST *&node);

View File

@@ -159,6 +159,9 @@ private slots:
void objc_method_attributes_1(); void objc_method_attributes_1();
void objc_selector_error_recovery_1(); void objc_selector_error_recovery_1();
void objc_selector_error_recovery_2(); void objc_selector_error_recovery_2();
void objc_try_statement_1();
void objc_try_statement_2();
void objc_try_statement_3();
// expressions with (square) brackets // expressions with (square) brackets
void normal_array_access(); void normal_array_access();
@@ -1380,6 +1383,60 @@ void tst_AST::objc_selector_error_recovery_2()
QVERIFY(ast); QVERIFY(ast);
} }
void tst_AST::objc_try_statement_1()
{
QSharedPointer<TranslationUnit> unit(
parseDeclaration(
"\n"
"void tst() {\n"
" @try {\n"
" something();\n"
" }\n"
"}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
QCOMPARE(diag.errorCount, 0);
}
void tst_AST::objc_try_statement_2()
{
QSharedPointer<TranslationUnit> unit(
parseDeclaration(
"void tst() {\n"
" @try {\n"
" something();\n"
" } @catch (NSException *e) {\n"
" another_thing();\n"
" } @catch (UIException *e) { \n"
" one_more_thing();\n"
" } @finally {\n"
" nothing();\n"
" }\n"
"}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
QCOMPARE(diag.errorCount, 0);
}
void tst_AST::objc_try_statement_3()
{
QSharedPointer<TranslationUnit> unit(
parseDeclaration(
"void tst() {\n"
" @try {\n"
" get_banana();\n"
" } @catch (...) {\n"
" printf(\"Oek?\");\n"
" }\n"
"}\n"
));
AST *ast = unit->ast();
QVERIFY(ast);
QCOMPARE(diag.errorCount, 0);
}
void tst_AST::normal_array_access() void tst_AST::normal_array_access()
{ {
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n" QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"