forked from qt-creator/qt-creator
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: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
committed by
Erik Verbruggen
parent
f7de8c934a
commit
2ead48fb26
107
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
107
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -3066,7 +3066,7 @@ bool Parser::parseStatement(StatementAST *&node)
|
|||||||
return parseSwitchStatement(node);
|
return parseSwitchStatement(node);
|
||||||
|
|
||||||
case T_TRY:
|
case T_TRY:
|
||||||
return parseTryBlockStatement(node);
|
return parseTryBlockStatement(node, 0);
|
||||||
|
|
||||||
case T_CASE:
|
case T_CASE:
|
||||||
case T_DEFAULT:
|
case T_DEFAULT:
|
||||||
@@ -4027,44 +4027,46 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *de
|
|||||||
node = ast;
|
node = ast;
|
||||||
return true;
|
return true;
|
||||||
} else if (! _inFunctionBody && declarator && (LA() == T_COLON || LA() == T_LBRACE || LA() == T_TRY)) {
|
} else if (! _inFunctionBody && declarator && (LA() == T_COLON || LA() == T_LBRACE || LA() == T_TRY)) {
|
||||||
CtorInitializerAST *ctor_initializer = 0;
|
if (LA() == T_TRY) {
|
||||||
bool hasCtorInitializer = false;
|
FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
|
||||||
if (LA() == T_COLON) {
|
ast->qt_invokable_token = qt_invokable_token;
|
||||||
hasCtorInitializer = true;
|
ast->decl_specifier_list = decl_specifier_seq;
|
||||||
parseCtorInitializer(ctor_initializer);
|
ast->declarator = firstDeclarator;
|
||||||
|
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_LBRACE) {
|
if (LA() == T_COLON) {
|
||||||
const unsigned pos = cursor();
|
hasCtorInitializer = true;
|
||||||
|
parseCtorInitializer(ctor_initializer);
|
||||||
for (int n = 0; n < 3 && LA(); consumeToken(), ++n)
|
|
||||||
if (LA() == T_LBRACE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (LA() != T_LBRACE) {
|
if (LA() != T_LBRACE) {
|
||||||
error(pos, "unexpected token `%s'", _translationUnit->spell(pos));
|
const unsigned pos = cursor();
|
||||||
rewind(pos);
|
|
||||||
|
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) {
|
if (LA() == T_LBRACE || hasCtorInitializer) {
|
||||||
FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
|
FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST;
|
||||||
ast->qt_invokable_token = qt_invokable_token;
|
ast->qt_invokable_token = qt_invokable_token;
|
||||||
ast->decl_specifier_list = decl_specifier_seq;
|
ast->decl_specifier_list = decl_specifier_seq;
|
||||||
ast->declarator = firstDeclarator;
|
ast->declarator = firstDeclarator;
|
||||||
ast->ctor_initializer = ctor_initializer;
|
ast->ctor_initializer = ctor_initializer;
|
||||||
parseFunctionBody(ast->function_body);
|
parseFunctionBody(ast->function_body);
|
||||||
node = ast;
|
node = ast;
|
||||||
return true; // recognized a function definition.
|
return true; // recognized a function definition.
|
||||||
} else 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);
|
|
||||||
node = ast;
|
|
||||||
return true; // recognized a function definition.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4124,13 +4126,50 @@ bool Parser::parseFunctionBody(StatementAST *&node)
|
|||||||
return parsed;
|
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();
|
DEBUG_THIS_RULE();
|
||||||
|
|
||||||
if (LA() == T_TRY) {
|
if (LA() == T_TRY) {
|
||||||
TryBlockStatementAST *ast = new (_pool) TryBlockStatementAST;
|
TryBlockStatementAST *ast = new (_pool) TryBlockStatementAST;
|
||||||
|
// try
|
||||||
ast->try_token = consumeToken();
|
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);
|
parseCompoundStatement(ast->statement);
|
||||||
|
// handler-seq
|
||||||
CatchClauseListAST **catch_clause_ptr = &ast->catch_clause_list;
|
CatchClauseListAST **catch_clause_ptr = &ast->catch_clause_list;
|
||||||
while (parseCatchClause(*catch_clause_ptr))
|
while (parseCatchClause(*catch_clause_ptr))
|
||||||
catch_clause_ptr = &(*catch_clause_ptr)->next;
|
catch_clause_ptr = &(*catch_clause_ptr)->next;
|
||||||
|
|||||||
2
src/libs/3rdparty/cplusplus/Parser.h
vendored
2
src/libs/3rdparty/cplusplus/Parser.h
vendored
@@ -165,7 +165,7 @@ public:
|
|||||||
bool parseTemplateParameter(DeclarationAST *&node);
|
bool parseTemplateParameter(DeclarationAST *&node);
|
||||||
bool parseTemplateParameterList(DeclarationListAST *&node);
|
bool parseTemplateParameterList(DeclarationListAST *&node);
|
||||||
bool parseThrowExpression(ExpressionAST *&node);
|
bool parseThrowExpression(ExpressionAST *&node);
|
||||||
bool parseTryBlockStatement(StatementAST *&node);
|
bool parseTryBlockStatement(StatementAST *&node, CtorInitializerAST **placeholder);
|
||||||
bool parseCatchClause(CatchClauseListAST *&node);
|
bool parseCatchClause(CatchClauseListAST *&node);
|
||||||
bool parseTypeId(ExpressionAST *&node);
|
bool parseTypeId(ExpressionAST *&node);
|
||||||
bool parseTypeIdList(ExpressionListAST *&node);
|
bool parseTypeIdList(ExpressionListAST *&node);
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ private slots:
|
|||||||
void cpp_constructor_one_named_arg();
|
void cpp_constructor_one_named_arg();
|
||||||
void cpp_constructor_no_arg();
|
void cpp_constructor_no_arg();
|
||||||
void cpp_constructor_multiple_args();
|
void cpp_constructor_multiple_args();
|
||||||
|
void cpp_constructor_function_try_catch();
|
||||||
|
|
||||||
// objc++
|
// objc++
|
||||||
void objc_simple_class();
|
void objc_simple_class();
|
||||||
@@ -1204,6 +1205,27 @@ void tst_AST::cpp_constructor_multiple_args()
|
|||||||
QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0);
|
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()
|
void tst_AST::objc_simple_class()
|
||||||
{
|
{
|
||||||
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
|
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user