diff options
-rw-r--r-- | src/shared/cplusplus/Parser.cpp | 105 | ||||
-rw-r--r-- | src/shared/cplusplus/Parser.h | 3 | ||||
-rw-r--r-- | tests/auto/cplusplus/ast/tst_ast.cpp | 76 |
3 files changed, 165 insertions, 19 deletions
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index d754b234f4..e60751305a 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -56,7 +56,7 @@ #include <cstdlib> #include <cstring> #include <cassert> -#include <QDebug> + CPLUSPLUS_BEGIN_NAMESPACE Parser::Parser(TranslationUnit *unit) @@ -2041,10 +2041,68 @@ bool Parser::maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const { if (! simpleDecl->declarators) { SpecifierAST *spec = simpleDecl->decl_specifier_seq; - if (spec && ! spec->next && spec->asNamedTypeSpecifier()) { + + if (spec && ! spec->next && spec->asNamedTypeSpecifier()) return true; + } + + return false; +} + +bool Parser::isPointerDeclaration(DeclarationStatementAST *ast) const +{ + if (! ast) + return false; + + if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) { + if (SpecifierAST *spec = declaration->decl_specifier_seq) { + if (spec->asNamedTypeSpecifier() && ! spec->next) { + if (DeclaratorListAST *declarators = declaration->declarators) { + if (DeclaratorAST *declarator = declarators->declarator) { + if (declarator->ptr_operators && declarator->equals_token && declarator->initializer) { + return true; + } + } + } + } } } + + return false; +} + +bool Parser::maybeAmbiguousStatement(DeclarationStatementAST *ast) const +{ + if (! ast) + return false; + + if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) { + if (SpecifierAST *spec = declaration->decl_specifier_seq) { + if (spec->asNamedTypeSpecifier() && ! spec->next) { + if (DeclaratorListAST *declarators = declaration->declarators) { + if (DeclaratorAST *declarator = declarators->declarator) { + if (declarator->core_declarator && + declarator->core_declarator->asNestedDeclarator()) { + // recognized name(id-expression) + return true; + } + } + } + } + + } else if (DeclaratorListAST *declarators = declaration->declarators) { + // no decl_specifiers... + if (DeclaratorAST *declarator = declarators->declarator) { + if (declarator->postfix_declarators && declarator->postfix_declarators->asFunctionDeclarator() + && ! declarator->initializer) { + return false; + } + } + + return true; + } + } + return false; } @@ -2055,31 +2113,35 @@ bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node) unsigned start = cursor(); bool blocked = blockErrors(true); + if (parseDeclarationStatement(node)) { DeclarationStatementAST *stmt = static_cast<DeclarationStatementAST *>(node); - SimpleDeclarationAST *simpleDecl = 0; - if (stmt->declaration) - simpleDecl = stmt->declaration->asSimpleDeclaration(); - if (simpleDecl && simpleDecl->decl_specifier_seq && - ! maybeFunctionCall(simpleDecl) && ! maybeSimpleExpression(simpleDecl)) { + if (isPointerDeclaration(stmt)) { + blockErrors(blocked); + return true; + } + + if (! maybeAmbiguousStatement(stmt)) { unsigned end_of_declaration_statement = cursor(); rewind(start); + StatementAST *expression = 0; - if (! parseExpressionStatement(expression) || cursor() != end_of_declaration_statement) { - rewind(end_of_declaration_statement); - } else { - ExpressionOrDeclarationStatementAST *ast = - new (_pool) ExpressionOrDeclarationStatementAST; + if (parseExpressionStatement(expression) && cursor() == end_of_declaration_statement) { + // it's an ambiguous expression-or-declaration statement. + ExpressionOrDeclarationStatementAST *ast = new (_pool) ExpressionOrDeclarationStatementAST; ast->declaration = node; ast->expression = expression; node = ast; } + + rewind(end_of_declaration_statement); blockErrors(blocked); return true; } } + // it's not a declaration statement. blockErrors(blocked); rewind(start); return parseExpressionStatement(node); @@ -2653,6 +2715,12 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, return false; } + // if there is no valid declarator + // and it doesn't look like a fwd or a class declaration + // then it's not a declarations + if (! declarator && ! maybeForwardOrClassDeclaration(decl_specifier_seq)) + return false; + DeclaratorAST *firstDeclarator = declarator; if (declarator) { @@ -2709,6 +2777,19 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, return false; } +bool Parser::maybeForwardOrClassDeclaration(SpecifierAST *decl_specifier_seq) const +{ + // look at the decl_specifier for possible fwd or class declarations. + if (SpecifierAST *spec = decl_specifier_seq) { + if (! spec->next && (spec->asElaboratedTypeSpecifier() || + spec->asEnumSpecifier() || + spec->asClassSpecifier())) + return true; + } + + return false; +} + bool Parser::parseFunctionBody(StatementAST *&node) { if (_translationUnit->skipFunctionBody()) { diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index 2f274e93ab..1dd204d154 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -264,8 +264,11 @@ public: void match(int kind, unsigned *token); + bool maybeAmbiguousStatement(DeclarationStatementAST *ast) const; bool maybeFunctionCall(SimpleDeclarationAST *simpleDecl) const; bool maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const; + bool maybeForwardOrClassDeclaration(SpecifierAST *decl_specifier_seq) const; + bool isPointerDeclaration(DeclarationStatementAST *ast) const; private: bool switchTemplateArguments(bool templateArguments); diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 45b6088c9f..25871aea12 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -58,6 +58,12 @@ private slots: void while_condition_statement(); void for_statement(); void cpp_initializer_or_function_declaration(); + void simple_declaration_1(); + void function_call_1(); + void function_call_2(); + void function_call_3(); + void nested_deref_expression(); + void assignment_1(); // objc++ void objc_attributes_followed_by_at_keyword(); @@ -78,6 +84,19 @@ void tst_AST::gcc_attributes_1() )); } +void tst_AST::simple_declaration_1() +{ + QSharedPointer<TranslationUnit> unit(parseStatement("\n" +"a * b = 10;" + )); + + AST *ast = unit->ast(); + QVERIFY(ast); + + DeclarationStatementAST *declStmt = ast->asDeclarationStatement(); + QVERIFY(declStmt); +} + void tst_AST::simple_name() { QSharedPointer<TranslationUnit> unit(parseExpression("a")); @@ -161,7 +180,7 @@ void tst_AST::new_expression_2() void tst_AST::condition_1() { QSharedPointer<TranslationUnit> unit(parseExpression("\n" -"(x < 0 && y > (int) a" +"(x < 0 && y > (int) a)" )); AST *ast = unit->ast(); @@ -178,6 +197,46 @@ void tst_AST::init_1() QVERIFY(ast != 0); } +void tst_AST::function_call_1() +{ + QSharedPointer<TranslationUnit> unit(parseStatement("retranslateUi(blah);")); + AST *ast = unit->ast(); + QVERIFY(ast != 0); + QVERIFY(ast->asExpressionStatement()); +} + +void tst_AST::function_call_2() +{ + QSharedPointer<TranslationUnit> unit(parseStatement("retranslateUi(10);")); + AST *ast = unit->ast(); + QVERIFY(ast != 0); + QVERIFY(ast->asExpressionStatement()); +} + +void tst_AST::function_call_3() +{ + QSharedPointer<TranslationUnit> unit(parseStatement("(*blah) = 10;")); + AST *ast = unit->ast(); + QVERIFY(ast != 0); + QVERIFY(ast->asExpressionStatement()); +} + +void tst_AST::nested_deref_expression() +{ + QSharedPointer<TranslationUnit> unit(parseStatement("(*blah);")); + AST *ast = unit->ast(); + QVERIFY(ast != 0); + QVERIFY(ast->asExpressionStatement()); +} + +void tst_AST::assignment_1() +{ + QSharedPointer<TranslationUnit> unit(parseStatement("a(x) = 3;")); + AST *ast = unit->ast(); + QVERIFY(ast != 0); + QVERIFY(ast->asExpressionStatement()); +} + void tst_AST::if_statement() { QSharedPointer<TranslationUnit> unit(parseStatement("if (a) b;")); @@ -195,7 +254,7 @@ void tst_AST::if_statement() QCOMPARE(stmt->else_token, 0U); QVERIFY(stmt->else_statement == 0); - // check the `then' statement + // check the `then' statement1 ExpressionStatementAST *then_stmt = stmt->statement->asExpressionStatement(); QVERIFY(then_stmt != 0); QVERIFY(then_stmt->expression != 0); @@ -435,7 +494,7 @@ void tst_AST::normal_array_access() { QSharedPointer<TranslationUnit> unit(parseDeclaration("\n" "int f() {\n" - " int a[15];\n" + " int a[10];\n" " int b = 1;\n" " return a[b];\n" "}" @@ -447,7 +506,10 @@ void tst_AST::normal_array_access() QVERIFY(func); StatementListAST *bodyStatements = func->function_body->asCompoundStatement()->statements; - QVERIFY(bodyStatements && bodyStatements->next && bodyStatements->next->next && bodyStatements->next->next->statement); + QVERIFY(bodyStatements); + QVERIFY(bodyStatements->next); + QVERIFY(bodyStatements->next->next); + QVERIFY(bodyStatements->next->next->statement); ExpressionAST *expr = bodyStatements->next->next->statement->asReturnStatement()->expression; QVERIFY(expr); @@ -536,9 +598,9 @@ void tst_AST::objc_msg_send_expression() QVERIFY(bodyStatements && bodyStatements->next && !bodyStatements->next->next && bodyStatements->next->statement); {// check the NSObject declaration - ExpressionOrDeclarationStatementAST *firstStatement = bodyStatements->statement->asExpressionOrDeclarationStatement(); - QVERIFY(firstStatement && firstStatement->declaration && firstStatement->declaration->asDeclarationStatement()); - DeclarationAST *objDecl = firstStatement->declaration->asDeclarationStatement()->declaration; + DeclarationStatementAST *firstStatement = bodyStatements->statement->asDeclarationStatement(); + QVERIFY(firstStatement); + DeclarationAST *objDecl = firstStatement->declaration; QVERIFY(objDecl); SimpleDeclarationAST *simpleDecl = objDecl->asSimpleDeclaration(); QVERIFY(simpleDecl); |