From 23085895d6c11081c16649107f5a0535671fc658 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 18 Jul 2013 10:04:28 +0200 Subject: [PATCH] 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 --- src/libs/3rdparty/cplusplus/Parser.cpp | 48 ++++++++++++++++++++++ src/libs/3rdparty/cplusplus/Parser.h | 1 + tests/auto/cplusplus/ast/tst_ast.cpp | 57 ++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 9c6804219bc..9a9c9ced782 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -333,6 +333,7 @@ bool Parser::skipUntilStatement() case T_USING: return true; + case T_AT_TRY: case T_AT_SYNCHRONIZED: if (objCEnabled()) return true; @@ -3106,6 +3107,9 @@ bool Parser::parseStatement(StatementAST *&node) return true; } + case T_AT_TRY: + return objCEnabled() && parseObjCTryStatement(node); + case T_AT_SYNCHRONIZED: return objCEnabled() && parseObjCSynchronizedStatement(node); @@ -4404,6 +4408,50 @@ bool Parser::parseObjCStringLiteral(ExpressionAST *&node) 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) { DEBUG_THIS_RULE(); diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index 978b1f99a19..71c3afa11b0 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -222,6 +222,7 @@ public: bool parseObjCProtocol(DeclarationAST *&node, SpecifierListAST *attributes = 0); + bool parseObjCTryStatement(StatementAST *&node); bool parseObjCSynchronizedStatement(StatementAST *&node); bool parseObjCEncodeExpression(ExpressionAST *&node); bool parseObjCProtocolExpression(ExpressionAST *&node); diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 6bfda0f5035..f17de6b613d 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -159,6 +159,9 @@ private slots: void objc_method_attributes_1(); void objc_selector_error_recovery_1(); 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 void normal_array_access(); @@ -1380,6 +1383,60 @@ void tst_AST::objc_selector_error_recovery_2() QVERIFY(ast); } +void tst_AST::objc_try_statement_1() +{ + QSharedPointer 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 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 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() { QSharedPointer unit(parseDeclaration("\n"