Commit 2ead48fb authored by Sergey Shambir's avatar Sergey Shambir Committed by Erik Verbruggen
Browse files

CPlusPlus: fixed parsing function-try-catch with ctor-initializer



C++ standard defines that 'try' should be before optional ctor
initializer, so wrong order changed. Added documentation to
parseTryBlockStatement and new test.

Task-number: QTCREATORBUG-9064
Change-Id: Id19cdc53c034cb1232ae27e0bfe36d85b7ad0452
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent f7de8c93
......@@ -3066,7 +3066,7 @@ bool Parser::parseStatement(StatementAST *&node)
return parseSwitchStatement(node);
case T_TRY:
return parseTryBlockStatement(node);
return parseTryBlockStatement(node, 0);
case T_CASE:
case T_DEFAULT:
......@@ -4027,44 +4027,46 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *de
node = ast;
return true;
} else if (! _inFunctionBody && declarator && (LA() == T_COLON || LA() == T_LBRACE || LA() == T_TRY)) {
CtorInitializerAST *ctor_initializer = 0;
bool hasCtorInitializer = false;
if (LA() == T_COLON) {
hasCtorInitializer = true;
parseCtorInitializer(ctor_initializer);
if (LA() != T_LBRACE) {
const unsigned pos = cursor();
for (int n = 0; n < 3 && LA(); consumeToken(), ++n)
if (LA() == T_LBRACE)
break;
if (LA() != T_LBRACE) {
error(pos, "unexpected token `%s'", _translationUnit->spell(pos));
rewind(pos);
}
}
}
if (LA() == T_LBRACE || hasCtorInitializer) {
FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
ast->qt_invokable_token = qt_invokable_token;
ast->decl_specifier_list = decl_specifier_seq;
ast->declarator = firstDeclarator;
ast->ctor_initializer = ctor_initializer;
parseFunctionBody(ast->function_body);
node = ast;
return true; // recognized a function definition.
} else if (LA() == T_TRY) {
if (LA() == T_TRY) {
FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
ast->qt_invokable_token = qt_invokable_token;
ast->decl_specifier_list = decl_specifier_seq;
ast->declarator = firstDeclarator;
ast->ctor_initializer = ctor_initializer;
parseTryBlockStatement(ast->function_body);
parseTryBlockStatement(ast->function_body, &ast->ctor_initializer);
node = ast;
return true; // recognized a function definition.
} else {
CtorInitializerAST *ctor_initializer = 0;
bool hasCtorInitializer = false;
if (LA() == T_COLON) {
hasCtorInitializer = true;
parseCtorInitializer(ctor_initializer);
if (LA() != T_LBRACE) {
const unsigned pos = cursor();
for (int n = 0; n < 3 && LA(); consumeToken(), ++n)
if (LA() == T_LBRACE)
break;
if (LA() != T_LBRACE) {
error(pos, "unexpected token `%s'", _translationUnit->spell(pos));
rewind(pos);
}
}
}
if (LA() == T_LBRACE || hasCtorInitializer) {
FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
ast->qt_invokable_token = qt_invokable_token;
ast->decl_specifier_list = decl_specifier_seq;
ast->declarator = firstDeclarator;
ast->ctor_initializer = ctor_initializer;
parseFunctionBody(ast->function_body);
node = ast;
return true; // recognized a function definition.
}
}
}
......@@ -4124,13 +4126,50 @@ bool Parser::parseFunctionBody(StatementAST *&node)
return parsed;
}
bool Parser::parseTryBlockStatement(StatementAST *&node)
/**
* Parses both try-block and function-try-block
* @param placeholder Non-null for function-try-block in around constructor
*
* try-block:
* try compound-statement handler-seq
* function-try-block:
* try [ctor-initializer] compound-statement handler-seq
*/
bool Parser::parseTryBlockStatement(StatementAST *&node, CtorInitializerAST **placeholder)
{
DEBUG_THIS_RULE();
if (LA() == T_TRY) {
TryBlockStatementAST *ast = new (_pool) TryBlockStatementAST;
// try
ast->try_token = consumeToken();
// [ctor-initializer]
if (LA() == T_COLON) {
const unsigned colonPos = cursor();
CtorInitializerAST *ctor_initializer = 0;
parseCtorInitializer(ctor_initializer);
if (LA() != T_LBRACE) {
const unsigned pos = cursor();
for (int n = 0; n < 3 && LA(); consumeToken(), ++n)
if (LA() == T_LBRACE)
break;
if (LA() != T_LBRACE) {
error(pos, "unexpected token `%s'", _translationUnit->spell(pos));
rewind(pos);
}
}
if (placeholder)
*placeholder = ctor_initializer;
else
error(colonPos, "constructor initializer not allowed inside function body");
}
// compound-statement
parseCompoundStatement(ast->statement);
// handler-seq
CatchClauseListAST **catch_clause_ptr = &ast->catch_clause_list;
while (parseCatchClause(*catch_clause_ptr))
catch_clause_ptr = &(*catch_clause_ptr)->next;
......
......@@ -165,7 +165,7 @@ public:
bool parseTemplateParameter(DeclarationAST *&node);
bool parseTemplateParameterList(DeclarationListAST *&node);
bool parseThrowExpression(ExpressionAST *&node);
bool parseTryBlockStatement(StatementAST *&node);
bool parseTryBlockStatement(StatementAST *&node, CtorInitializerAST **placeholder);
bool parseCatchClause(CatchClauseListAST *&node);
bool parseTypeId(ExpressionAST *&node);
bool parseTypeIdList(ExpressionListAST *&node);
......
......@@ -145,6 +145,7 @@ private slots:
void cpp_constructor_one_named_arg();
void cpp_constructor_no_arg();
void cpp_constructor_multiple_args();
void cpp_constructor_function_try_catch();
// objc++
void objc_simple_class();
......@@ -1204,6 +1205,27 @@ void tst_AST::cpp_constructor_multiple_args()
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::cpp_constructor_function_try_catch()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("QFileInfo::QFileInfo(QString name, QString type)"
" try : m_name(name), m_type(type) {}"
" catch (...) {}"));
AST *ast = unit->ast();
QVERIFY(ast != 0);
FunctionDefinitionAST *funDef = ast->asFunctionDefinition();
QVERIFY(funDef != 0);
QVERIFY(funDef->ctor_initializer != 0);
QVERIFY(funDef->declarator != 0);
QVERIFY(funDef->declarator->postfix_declarator_list != 0);
QVERIFY(funDef->declarator->postfix_declarator_list->lastValue() != 0);
FunctionDeclaratorAST *funDecl = funDef->declarator->postfix_declarator_list->lastValue()->asFunctionDeclarator();
QVERIFY(funDecl != 0);
QVERIFY(funDecl->parameter_declaration_clause != 0);
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
}
void tst_AST::objc_simple_class()
{
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment