diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index bf192b69e8af6f15e6ed4bc6bb02846d3ed4f37b..c4df234771010b56912f453626bd987f96bbb4c2 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -54,6 +54,7 @@ #include "Literals.h" #include "ObjectiveCTypeQualifiers.h" #include "QtContextKeywords.h" +#include <string> #include <cstdio> // for putchar #ifdef _MSC_VER @@ -74,14 +75,14 @@ class DebugRule { static int depth; public: - DebugRule(const char *name, int kind, unsigned idx) + DebugRule(const char *name, const char *spell, unsigned idx, bool blocked) : name(name) { for (int i = 0; i <= depth; ++i) - putchar('-'); + fputc('-', stderr); ++depth; - printf(" %s, ahead: '%s' (%d)\n", name, Token::name(kind), idx); + fprintf(stderr, " %s, ahead: '%s' (%d) - block-errors: %d\n", name, spell, idx, blocked); } ~DebugRule() @@ -180,7 +181,7 @@ inline bool isRightAssociative(int tokenKind) } // end of anonymous namespace #ifndef CPLUSPLUS_NO_DEBUG_RULE -# define DEBUG_THIS_RULE() DebugRule __debug_rule__(__func__, tok().f.kind, cursor()) +# define DEBUG_THIS_RULE() DebugRule __debug_rule__(__func__, tok().spell(), cursor(), _translationUnit->blockErrors()) #else # define DEBUG_THIS_RULE() do {} while (0) #endif @@ -403,7 +404,7 @@ void Parser::match(int kind, unsigned *token) bool Parser::parseClassOrNamespaceName(NameAST *&node) { DEBUG_THIS_RULE(); - if (LA() == T_IDENTIFIER) { + if (LA() == T_IDENTIFIER && (LA(2) == T_COLON_COLON || LA(2) == T_LESS)) { unsigned identifier_token = cursor(); if (LA(2) == T_LESS && parseTemplateId(node) && LA() == T_COLON_COLON) @@ -419,7 +420,7 @@ bool Parser::parseClassOrNamespaceName(NameAST *&node) } } else if (LA() == T_TEMPLATE) { unsigned template_token = consumeToken(); - if (parseTemplateId(node, template_token)) + if (parseTemplateId(node, template_token) && LA() == T_COLON_COLON) return true; rewind(template_token); } @@ -500,7 +501,19 @@ bool Parser::parseNestedNameSpecifierOpt(NestedNameSpecifierListAST *&name, bool bool Parser::parseName(NameAST *&node, bool acceptTemplateId) { DEBUG_THIS_RULE(); - unsigned global_scope_token = 0; + unsigned global_scope_token = 0; + + switch (LA()) { + case T_COLON_COLON: + case T_IDENTIFIER: + case T_TILDE: // destructor-name-id + case T_OPERATOR: // operator-name-id + case T_TEMPLATE: // template introduced template-id + break; + default: + return false; + } + if (LA() == T_COLON_COLON) global_scope_token = consumeToken(); @@ -910,7 +923,12 @@ bool Parser::parseAsmDefinition(DeclarationAST *&node) } } else if (LA() == T_COLON_COLON) { consumeToken(); - parseAsmClobberList(); + parseAsmOperandList(); + + if (LA() == T_COLON) { + consumeToken(); + parseAsmClobberList(); + } } match(T_RPAREN, &ast->rparen_token); match(T_SEMICOLON, &ast->semicolon_token); @@ -1160,7 +1178,7 @@ bool Parser::parseTemplateArgument(ExpressionAST *&node) rewind(start); bool previousTemplateArguments = switchTemplateArguments(true); - bool parsed = parseLogicalOrExpression(node); + bool parsed = parseConstantExpression(node); (void) switchTemplateArguments(previousTemplateArguments); return parsed; } @@ -1215,21 +1233,21 @@ bool Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq, return decl_specifier_seq != 0; } -bool Parser::parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node) +bool Parser::parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list) { DEBUG_THIS_RULE(); unsigned start = cursor(); bool blocked = blockErrors(true); - if (parseDeclarator(node)) { + if (parseDeclarator(node, decl_specifier_list)) { blockErrors(blocked); return true; } blockErrors(blocked); rewind(start); - return parseAbstractDeclarator(node); + return parseAbstractDeclarator(node, decl_specifier_list); } -bool Parser::parseCoreDeclarator(DeclaratorAST *&node) +bool Parser::parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, bool declaringClass) { DEBUG_THIS_RULE(); unsigned start = cursor(); @@ -1264,13 +1282,13 @@ bool Parser::parseCoreDeclarator(DeclaratorAST *&node) node = ast; return true; } - } else if (LA() == T_LPAREN) { + } else if (decl_specifier_list && LA() == T_LPAREN) { if (attributes) warning(attributes->firstToken(), "unexpected attribtues"); unsigned lparen_token = consumeToken(); DeclaratorAST *declarator = 0; - if (parseDeclarator(declarator) && LA() == T_RPAREN) { + if (parseDeclarator(declarator, decl_specifier_list) && LA() == T_RPAREN) { NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST; nested_declarator->lparen_token = lparen_token; nested_declarator->declarator = declarator; @@ -1286,10 +1304,10 @@ bool Parser::parseCoreDeclarator(DeclaratorAST *&node) return false; } -bool Parser::parseDeclarator(DeclaratorAST *&node, bool stopAtCppInitializer) +bool Parser::parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, bool declaringClass) { DEBUG_THIS_RULE(); - if (! parseCoreDeclarator(node)) + if (! parseCoreDeclarator(node, decl_specifier_list, declaringClass)) return false; PostfixDeclaratorListAST **postfix_ptr = &node->postfix_declarator_list; @@ -1298,7 +1316,7 @@ bool Parser::parseDeclarator(DeclaratorAST *&node, bool stopAtCppInitializer) unsigned startOfPostDeclarator = cursor(); if (LA() == T_LPAREN) { - if (stopAtCppInitializer) { + if (! declaringClass) { unsigned lparen_token = cursor(); ExpressionAST *initializer = 0; @@ -1390,7 +1408,7 @@ bool Parser::parseDeclarator(DeclaratorAST *&node, bool stopAtCppInitializer) return true; } -bool Parser::parseAbstractCoreDeclarator(DeclaratorAST *&node) +bool Parser::parseAbstractCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list) { DEBUG_THIS_RULE(); @@ -1403,7 +1421,7 @@ bool Parser::parseAbstractCoreDeclarator(DeclaratorAST *&node) if (LA() == T_LPAREN) { unsigned lparen_token = consumeToken(); DeclaratorAST *declarator = 0; - if (parseAbstractDeclarator(declarator) && LA() == T_RPAREN) { + if (parseAbstractDeclarator(declarator, decl_specifier_list) && LA() == T_RPAREN) { NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST; nested_declarator->lparen_token = lparen_token; nested_declarator->declarator = declarator; @@ -1426,10 +1444,10 @@ bool Parser::parseAbstractCoreDeclarator(DeclaratorAST *&node) return true; } -bool Parser::parseAbstractDeclarator(DeclaratorAST *&node) +bool Parser::parseAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list) { DEBUG_THIS_RULE(); - if (! parseAbstractCoreDeclarator(node)) + if (! parseAbstractCoreDeclarator(node, decl_specifier_list)) return false; PostfixDeclaratorListAST *postfix_declarators = 0, @@ -1638,7 +1656,7 @@ bool Parser::parseTypeId(ExpressionAST *&node) if (parseTypeSpecifier(type_specifier)) { TypeIdAST *ast = new (_pool) TypeIdAST; ast->type_specifier_list = type_specifier; - parseAbstractDeclarator(ast->declarator); + parseAbstractDeclarator(ast->declarator, type_specifier); node = ast; return true; } @@ -1714,7 +1732,7 @@ bool Parser::parseParameterDeclaration(DeclarationAST *&node) if (parseDeclSpecifierSeq(decl_specifier_seq)) { ParameterDeclarationAST *ast = new (_pool) ParameterDeclarationAST; ast->type_specifier_list = decl_specifier_seq; - parseDeclaratorOrAbstractDeclarator(ast->declarator); + parseDeclaratorOrAbstractDeclarator(ast->declarator, decl_specifier_seq); if (LA() == T_EQUAL) { ast->equal_token = consumeToken(); parseLogicalOrExpression(ast->expression); @@ -1726,6 +1744,32 @@ bool Parser::parseParameterDeclaration(DeclarationAST *&node) return false; } +const Identifier *Parser::className(ClassSpecifierAST *ast) const +{ + if (! ast) + return 0; + + return identifier(ast->name); +} + +const Identifier *Parser::identifier(NameAST *name) const +{ + if (! name) + return 0; + + if (QualifiedNameAST *q = name->asQualifiedName()) + name = q->unqualified_name; + + if (name) { + if (SimpleNameAST *simple = name->asSimpleName()) + return _translationUnit->identifier(simple->identifier_token); + else if (TemplateIdAST *template_id = name->asTemplateId()) + return _translationUnit->identifier(template_id->identifier_token); + } + + return 0; +} + bool Parser::parseClassSpecifier(SpecifierListAST *&node) { DEBUG_THIS_RULE(); @@ -1803,7 +1847,7 @@ bool Parser::parseClassSpecifier(SpecifierListAST *&node) unsigned start_declaration = cursor(); DeclarationAST *declaration = 0; - if (parseMemberSpecification(declaration)) { + if (parseMemberSpecification(declaration, ast)) { if (declaration) { // paranoia check *declaration_ptr = new (_pool) DeclarationListAST; (*declaration_ptr)->value = declaration; @@ -2107,7 +2151,7 @@ bool Parser::parseQtInterfaces(DeclarationAST *&node) // q-declare-metatype ::= // Q_DECLARE_METATYPE LPAREN name RPAREN SEMICOLON? [warning] -bool Parser::parseMemberSpecification(DeclarationAST *&node) +bool Parser::parseMemberSpecification(DeclarationAST *&node, ClassSpecifierAST *declaringClass) { DEBUG_THIS_RULE(); switch (LA()) { @@ -2132,7 +2176,7 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node) } match(T_COMMA, &ast->comma_token); (void) parseTypeSpecifier(ast->type_specifiers); - parseDeclarator(ast->declarator); + parseDeclarator(ast->declarator, ast->type_specifiers); match(T_RPAREN, &ast->rparen_token); node = ast; } return true; @@ -2166,7 +2210,7 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node) return parseQtInterfaces(node); default: - return parseSimpleDeclaration(node, /*acceptStructDeclarator=*/true); + return parseSimpleDeclaration(node, declaringClass); } // switch } @@ -2254,16 +2298,16 @@ bool Parser::parseEnumerator(EnumeratorListAST *&node) return false; } -bool Parser::parseInitDeclarator(DeclaratorAST *&node, - bool acceptStructDeclarator) +bool Parser::parseInitDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, + bool declaringClass) // ### rewrite me { DEBUG_THIS_RULE(); unsigned start = cursor(); - if (acceptStructDeclarator && LA() == T_COLON) { + if (declaringClass && LA() == T_COLON) { // anonymous bit-field declaration. - } else if (! parseDeclarator(node, /*stopAtCppInitializer = */ ! acceptStructDeclarator)) { + } else if (! parseDeclarator(node, decl_specifier_list, declaringClass)) { return false; } @@ -2274,15 +2318,18 @@ bool Parser::parseInitDeclarator(DeclaratorAST *&node, consumeToken(); } - if (acceptStructDeclarator && node && - ! node->postfix_declarator_list && - node->core_declarator && - node->core_declarator->asNestedDeclarator()) { +#if 0 + if (declaringClass && node && + ! node->postfix_declarator_list && + node->core_declarator && + node->core_declarator->asNestedDeclarator()) { + _translationUnit->warning(cursor(), "got here"); rewind(start); return false; } +#endif - if (acceptStructDeclarator && LA() == T_COLON + if (declaringClass && LA() == T_COLON && (! node || ! node->postfix_declarator_list)) { unsigned colon_token = consumeToken(); ExpressionAST *expression = 0; @@ -2295,7 +2342,7 @@ bool Parser::parseInitDeclarator(DeclaratorAST *&node, return true; } rewind(colon_token); - } else if (LA() == T_EQUAL || (! acceptStructDeclarator && LA() == T_LPAREN)) { + } else if (node->core_declarator && (LA() == T_EQUAL || (! declaringClass && LA() == T_LPAREN))) { parseInitializer(node->initializer, &node->equal_token); } return true; @@ -2635,6 +2682,7 @@ bool Parser::parseUnqualifiedName(NameAST *&node, bool acceptTemplateId) if (acceptTemplateId && LA(2) == T_LESS && parseTemplateId(node)) { if (! _templateArguments || (LA() == T_COMMA || LA() == T_GREATER || LA() == T_LPAREN || LA() == T_RPAREN || + LA() == T_STAR || LA() == T_AMPER || // ptr-operators LA() == T_COLON_COLON)) return true; } @@ -2843,104 +2891,135 @@ bool Parser::parseReturnStatement(StatementAST *&node) return false; } -bool Parser::isPointerDeclaration(DeclarationStatementAST *ast) const +bool Parser::maybeAmbiguousStatement(DeclarationStatementAST *ast, StatementAST *&node) { - if (! ast) - return false; + const unsigned start = ast->firstToken(); + const unsigned end = ast->lastToken(); + const bool blocked = blockErrors(true); - if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) { - if (SpecifierListAST *spec = declaration->decl_specifier_list) { - if (spec->value->asNamedTypeSpecifier() && ! spec->next) { - if (DeclaratorListAST *declarators = declaration->declarator_list) { - if (DeclaratorAST *declarator = declarators->value) { - if (declarator->ptr_operator_list && declarator->equal_token && declarator->initializer) { - return true; - } - } - } - } - } + bool maybeAmbiguous = false; + + StatementAST *stmt = 0; + if (parseExpressionStatement(stmt)) { + if (stmt->firstToken() == start && stmt->lastToken() == end) { + maybeAmbiguous = true; + node = stmt; } + } - return false; + rewind(end); + (void) blockErrors(blocked); + return maybeAmbiguous; } -bool Parser::maybeAmbiguousStatement(DeclarationStatementAST *ast) const +#if 1 +bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node) { - if (! ast) - return false; + DEBUG_THIS_RULE(); - if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) { - if (SpecifierListAST *spec = declaration->decl_specifier_list) { - if (spec->value->asNamedTypeSpecifier() && ! spec->next) { - if (DeclaratorListAST *declarators = declaration->declarator_list) { - if (DeclaratorAST *declarator = declarators->value) { - if (declarator->core_declarator && - declarator->core_declarator->asNestedDeclarator()) { - // recognized name(id-expression) - return true; - } - } - } - } + if (LA() == T_SEMICOLON) + return parseExpressionStatement(node); - } else if (DeclaratorListAST *declarators = declaration->declarator_list) { - // no decl_specifiers... - if (DeclaratorAST *declarator = declarators->value) { - if (declarator->postfix_declarator_list && declarator->postfix_declarator_list->value->asFunctionDeclarator() - && ! declarator->initializer) { - return false; - } - } + const unsigned start = cursor(); - return true; - } + if (lookAtCVQualifier() || lookAtStorageClassSpecifier() || lookAtBuiltinTypeSpecifier() || LA() == T_TYPENAME || LA() == T_ENUM || lookAtClassKey()) + return parseDeclarationStatement(node); + + if (LA() == T_IDENTIFIER || (LA() == T_COLON_COLON && LA(2) == T_IDENTIFIER)) { + const bool blocked = blockErrors(true); + + ExpressionAST *expression = 0; + if (parseExpression(expression) && LA() == T_SEMICOLON) { + const unsigned semicolon_token = consumeToken(); + + ExpressionStatementAST *as_expression = new (_pool) ExpressionStatementAST; + as_expression->expression = expression; + as_expression->semicolon_token = semicolon_token; + node = as_expression; // well, at least for now. + + if (BinaryExpressionAST *binary = expression->asBinaryExpression()) { + const int binop = _translationUnit->tokenKind(binary->binary_op_token); + if (binop == T_EQUAL) { + if (binary->left_expression->asBinaryExpression() != 0) { + (void) blockErrors(blocked); + node = as_expression; + return true; + } + } + } else if (CallAST *call = expression->asCall()) { + if (call->base_expression->asIdExpression() != 0) { + (void) blockErrors(blocked); + node = as_expression; + return true; + } + } + + rewind(start); + + DeclarationAST *declaration = 0; + if (parseSimpleDeclaration(declaration)) { + SimpleDeclarationAST *simple = declaration->asSimpleDeclaration(); + if (simple->semicolon_token == semicolon_token && simple->decl_specifier_list && simple->declarator_list) { + DeclarationStatementAST *as_declaration = new (_pool) DeclarationStatementAST; + as_declaration->declaration = declaration; + + if (simple->decl_specifier_list != 0 && simple->declarator_list != 0) { + node = as_declaration; + (void) blockErrors(blocked); + return true; + } + + ExpressionOrDeclarationStatementAST *ast = new (_pool) ExpressionOrDeclarationStatementAST; + ast->declaration = as_declaration; + ast->expression = as_expression; + node = ast; + } + } + rewind(semicolon_token + 1); + (void) blockErrors(blocked); + return true; } - return false; -} + rewind(start); + (void) blockErrors(blocked); + return parseDeclarationStatement(node); + } + rewind(start); + return parseExpressionStatement(node); +} +#else bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node) { - DEBUG_THIS_RULE(); - if (LA() == T_SEMICOLON) - return parseExpressionStatement(node); - - unsigned start = cursor(); - bool blocked = blockErrors(true); - - if (parseDeclarationStatement(node)) { - DeclarationStatementAST *stmt = static_cast<DeclarationStatementAST *>(node); + DEBUG_THIS_RULE(); + if (LA() == T_SEMICOLON) + return parseExpressionStatement(node); - if (isPointerDeclaration(stmt)) { - blockErrors(blocked); - return true; - } + const unsigned start = cursor(); + const bool startsWithName = LA() == T_COLON_COLON || LA() == T_IDENTIFIER; - if (! maybeAmbiguousStatement(stmt)) { - unsigned end_of_declaration_statement = cursor(); - rewind(start); - StatementAST *expression = 0; - 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; - } + if (! parseDeclarationStatement(node)) { + rewind(start); + return parseExpressionStatement(node); + } - rewind(end_of_declaration_statement); - blockErrors(blocked); - return true; - } + if (startsWithName) { + if (DeclarationStatementAST *as_declaration = node->asDeclarationStatement()) { + StatementAST *as_expression = 0; + if (maybeAmbiguousStatement(as_declaration, as_expression)) { + // it's an ambiguous expression-or-declaration statement. + ExpressionOrDeclarationStatementAST *ast = new (_pool) ExpressionOrDeclarationStatementAST; + ast->declaration = as_declaration; + ast->expression = as_expression; + node = ast; + } } + } - // it's not a declaration statement. - blockErrors(blocked); - rewind(start); - return parseExpressionStatement(node); + return true; } +#endif bool Parser::parseCondition(ExpressionAST *&node) { @@ -2951,7 +3030,7 @@ bool Parser::parseCondition(ExpressionAST *&node) SpecifierListAST *type_specifier = 0; if (parseTypeSpecifier(type_specifier)) { DeclaratorAST *declarator = 0; - if (parseInitDeclarator(declarator, /*acceptStructDeclarator=*/false)) { + if (parseInitDeclarator(declarator, type_specifier, /*declaringClass=*/false)) { if (declarator->initializer && declarator->equal_token) { ConditionAST *ast = new (_pool) ConditionAST; ast->type_specifier_list = type_specifier; @@ -3014,7 +3093,7 @@ bool Parser::parseForeachStatement(StatementAST *&node) bool blocked = blockErrors(true); if (parseTypeSpecifier(ast->type_specifier_list)) - parseDeclarator(ast->declarator); + parseDeclarator(ast->declarator, ast->type_specifier_list); if (! ast->type_specifier_list || ! ast->declarator) { ast->type_specifier_list = 0; @@ -3057,7 +3136,7 @@ bool Parser::parseForStatement(StatementAST *&node) ast->lparen_token = lparen_token; if (parseTypeSpecifier(ast->type_specifier_list)) - parseDeclarator(ast->declarator); + parseDeclarator(ast->declarator, ast->type_specifier_list); if ((ast->type_specifier_list || ast->declarator) && !peekAtObjCContextKeyword(Token_in)) { // woops, probably parsed too much: "in" got parsed as a declarator. Let's redo it: @@ -3065,7 +3144,7 @@ bool Parser::parseForStatement(StatementAST *&node) ast->declarator = 0; rewind(startOfTypeSpecifier); - parseDeclarator(ast->declarator); + parseDeclarator(ast->declarator, ast->type_specifier_list); } if (! ast->type_specifier_list || ! ast->declarator) { @@ -3440,13 +3519,11 @@ bool Parser::parseBuiltinTypeSpecifier(SpecifierListAST *&node) return false; } -bool Parser::parseSimpleDeclaration(DeclarationAST *&node, - bool acceptStructDeclarator) +bool Parser::parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *declaringClass) { DEBUG_THIS_RULE(); unsigned qt_invokable_token = 0; - if (acceptStructDeclarator - && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT || LA() == T_Q_INVOKABLE)) + if (declaringClass && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT || LA() == T_Q_INVOKABLE)) qt_invokable_token = consumeToken(); // parse a simple declaration, a function definition, @@ -3475,6 +3552,14 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, LA() == T_IDENTIFIER)) { startOfNamedTypeSpecifier = cursor(); if (parseName(named_type_specifier)) { + + if (LA() == T_LPAREN && identifier(named_type_specifier) == className(declaringClass)) { + // looks like a constructor declaration + rewind(startOfNamedTypeSpecifier); + break; + } + + NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST; spec->name = named_type_specifier; *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec); @@ -3532,7 +3617,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, if (LA() != T_SEMICOLON) { const bool maybeCtor = (LA() == T_LPAREN && named_type_specifier); - if (! parseInitDeclarator(declarator, acceptStructDeclarator) && maybeCtor) { + if (! parseInitDeclarator(declarator, decl_specifier_seq, declaringClass) && maybeCtor) { rewind(startOfNamedTypeSpecifier); named_type_specifier = 0; // pop the named type specifier from the decl-specifier-seq @@ -3543,7 +3628,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, break; } } - if (! parseInitDeclarator(declarator, acceptStructDeclarator)) + if (! parseInitDeclarator(declarator, decl_specifier_seq, declaringClass)) return false; } } @@ -3567,7 +3652,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, consumeToken(); // consume T_COMMA declarator = 0; - if (parseInitDeclarator(declarator, acceptStructDeclarator)) { + if (parseInitDeclarator(declarator, decl_specifier_seq, declaringClass)) { *declarator_ptr = new (_pool) DeclaratorListAST; (*declarator_ptr)->value = declarator; declarator_ptr = &(*declarator_ptr)->next; @@ -3724,7 +3809,7 @@ bool Parser::parseExceptionDeclaration(ExceptionDeclarationAST *&node) if (parseTypeSpecifier(type_specifier)) { ExceptionDeclarationAST *ast = new (_pool) ExceptionDeclarationAST; ast->type_specifier_list = type_specifier; - parseDeclaratorOrAbstractDeclarator(ast->declarator); + parseDeclaratorOrAbstractDeclarator(ast->declarator, type_specifier); node = ast; return true; } @@ -4427,7 +4512,8 @@ bool Parser::parseUnaryExpression(ExpressionAST *&node) } } - parseUnaryExpression(ast->expression); + parsePrimaryExpression(ast->expression); + node = ast; return true; } @@ -4715,7 +4801,7 @@ bool Parser::parseQtMethod(ExpressionAST *&node) QtMethodAST *ast = new (_pool) QtMethodAST; ast->method_token = consumeToken(); match(T_LPAREN, &ast->lparen_token); - if (! parseDeclarator(ast->declarator)) + if (! parseDeclarator(ast->declarator, /*decl_specifier_seq =*/ 0)) error(cursor(), "expected a function declarator before token `%s'", tok().spell()); match(T_RPAREN, &ast->rparen_token); @@ -5354,11 +5440,11 @@ bool Parser::parseObjCInterfaceMemberDeclaration(DeclarationAST *&node) case T_CLASS: case T_STRUCT: case T_UNION: { - return parseSimpleDeclaration(node, /*accept struct declarators */ true); + return parseSimpleDeclaration(node); } default: { - return parseSimpleDeclaration(node, /*accept struct declarators */ true); + return parseSimpleDeclaration(node); } // default } // switch @@ -5382,7 +5468,7 @@ bool Parser::parseObjCInstanceVariableDeclaration(DeclarationAST *&node) } default: - return parseSimpleDeclaration(node, true); + return parseSimpleDeclaration(node); } } @@ -5423,7 +5509,7 @@ bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierListAS match(T_RPAREN, &ast->rparen_token); } - if (parseSimpleDeclaration(ast->simple_declaration, /*accept-struct-declarators = */ true)) + if (parseSimpleDeclaration(ast->simple_declaration)) node = ast; else error(_tokenIndex, "expected a simple declaration"); @@ -5817,7 +5903,7 @@ bool Parser::parseTrailingReturnType(TrailingReturnTypeAST *&node) attr = &(*attr)->next; parseTrailingTypeSpecifierSeq(ast->type_specifiers); - parseAbstractDeclarator(ast->declarator); + parseAbstractDeclarator(ast->declarator, ast->type_specifiers); node = ast; return true; } @@ -5831,7 +5917,8 @@ bool Parser::parseTrailingTypeSpecifierSeq(SpecifierListAST *&node) void Parser::rewind(unsigned cursor) { #ifndef CPLUSPLUS_NO_DEBUG_RULE - printf("! rewinding from token %d to token %d\n", _tokenIndex, cursor); + if (cursor != _tokenIndex) + fprintf(stderr, "! rewinding from token %d to token %d\n", _tokenIndex, cursor); #endif if (cursor < _translationUnit->tokenCount()) diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index 11743346a4e9ebbcc2645476a82140ce2cbcf270..d5e0257f19bdec7fcbf8638edf5045ac6f74f44f 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -78,8 +78,8 @@ public: public: bool parseAccessSpecifier(SpecifierAST *&node); bool parseExpressionList(ExpressionListAST *&node); - bool parseAbstractCoreDeclarator(DeclaratorAST *&node); - bool parseAbstractDeclarator(DeclaratorAST *&node); + bool parseAbstractCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list); + bool parseAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list); bool parseEmptyDeclaration(DeclarationAST *&node); bool parseAccessDeclaration(DeclarationAST *&node); bool parseQtPropertyDeclaration(DeclarationAST *&node); @@ -110,12 +110,12 @@ public: bool parseConstantExpression(ExpressionAST *&node); bool parseCtorInitializer(CtorInitializerAST *&node); bool parseCvQualifiers(SpecifierListAST *&node); - bool parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node); + bool parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list); bool parseDeclaration(DeclarationAST *&node); - bool parseSimpleDeclaration(DeclarationAST *&node, bool acceptStructDeclarator = false); + bool parseSimpleDeclaration(DeclarationAST *&node, ClassSpecifierAST *declaringClass = 0); bool parseDeclarationStatement(StatementAST *&node); - bool parseCoreDeclarator(DeclaratorAST *&node); - bool parseDeclarator(DeclaratorAST *&node, bool stopAtCppInitializer = false); + bool parseCoreDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, bool declaringClass); + bool parseDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, bool declaringClass = false); bool parseDeleteExpression(ExpressionAST *&node); bool parseDoStatement(StatementAST *&node); bool parseElaboratedTypeSpecifier(SpecifierListAST *&node); @@ -134,7 +134,7 @@ public: bool parseFunctionBody(StatementAST *&node); bool parseIfStatement(StatementAST *&node); bool parseInclusiveOrExpression(ExpressionAST *&node); - bool parseInitDeclarator(DeclaratorAST *&node, bool acceptStructDeclarator); + bool parseInitDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_specifier_list, bool declaringClass); bool parseInitializerList(ExpressionListAST *&node); bool parseInitializer(ExpressionAST *&node, unsigned *equals_token); bool parseInitializerClause(ExpressionAST *&node); @@ -145,7 +145,7 @@ public: bool parseLogicalOrExpression(ExpressionAST *&node); bool parseMemInitializer(MemInitializerListAST *&node); bool parseMemInitializerList(MemInitializerListAST *&node); - bool parseMemberSpecification(DeclarationAST *&node); + bool parseMemberSpecification(DeclarationAST *&node, ClassSpecifierAST *declaringClass); bool parseMultiplicativeExpression(ExpressionAST *&node); bool parseTemplateId(NameAST *&node, unsigned template_token = 0); bool parseClassOrNamespaceName(NameAST *&node); @@ -287,11 +287,13 @@ public: bool lookAtBuiltinTypeSpecifier() const; bool lookAtClassKey() const; + const Identifier *className(ClassSpecifierAST *ast) const; + const Identifier *identifier(NameAST *name) const; + void match(int kind, unsigned *token); - bool maybeAmbiguousStatement(DeclarationStatementAST *ast) const; + bool maybeAmbiguousStatement(DeclarationStatementAST *ast, StatementAST *&node); bool maybeForwardOrClassDeclaration(SpecifierListAST *decl_specifier_seq) const; - bool isPointerDeclaration(DeclarationStatementAST *ast) const; int peekAtQtContextKeyword() const; diff --git a/src/shared/cplusplus/TranslationUnit.cpp b/src/shared/cplusplus/TranslationUnit.cpp index 29763530fdb9db7502d761efef5396aa9c27c0e6..f8c597051d13ae284a46fbd4b7ccbdf5a54982b1 100644 --- a/src/shared/cplusplus/TranslationUnit.cpp +++ b/src/shared/cplusplus/TranslationUnit.cpp @@ -295,7 +295,7 @@ bool TranslationUnit::parse(ParseMode mode) case ParseDeclarator: { DeclaratorAST *node = 0; - parsed = parser.parseDeclarator(node); + parsed = parser.parseDeclarator(node, /*decl_specifier_list =*/ 0); _ast = node; } break; diff --git a/src/shared/cplusplus/TranslationUnit.h b/src/shared/cplusplus/TranslationUnit.h index 734042b659ea2594f46e87bd2d2004a7df85a6e5..fc9643b4908ad59b5c8c41eb21d4b97d48e6797b 100644 --- a/src/shared/cplusplus/TranslationUnit.h +++ b/src/shared/cplusplus/TranslationUnit.h @@ -94,6 +94,7 @@ public: MemoryPool *memoryPool() const; AST *ast() const; + bool blockErrors() const { return f._blockErrors; } bool blockErrors(bool block); bool qtMocRunEnabled() const; diff --git a/tests/manual/plain-cplusplus/main.cpp b/tests/manual/plain-cplusplus/main.cpp index 156a46ba17192ff620ab872e92bae09cec4f8b7a..675ae41ce2c7fb6022f31c7c6b7bca3711ef25d0 100644 --- a/tests/manual/plain-cplusplus/main.cpp +++ b/tests/manual/plain-cplusplus/main.cpp @@ -42,6 +42,33 @@ void parse(const char *fileName, const char *source, unsigned size); int runWithSystemPreprocessor(int argc, char *argv[]); int runWithNewPreprocessor(int argc, char *argv[]); +struct V: public ASTVisitor +{ + V(TranslationUnit *unit) + : ASTVisitor(unit) {} + + virtual bool visit(FunctionDeclaratorAST *ast) + { + if (ast->as_cpp_initializer) { + if (! (ast->symbol && ast->symbol->scope())) + ; //translationUnit()->warning(ast->firstToken(), "resolved as function declaration"); + else if (ast->symbol->scope()->isNamespace() || ast->symbol->scope()->isTemplate()) + ; //translationUnit()->warning(ast->firstToken(), "resolved as function declaration"); + else if (ast->symbol->scope()->isBlock()) + ; //translationUnit()->warning(ast->firstToken(), "resolved as C++ initializer"); + else + translationUnit()->warning(ast->firstToken(), "ambiguous function declarator or C++ intializer"); + } + return true; + } + + virtual bool visit(ExpressionOrDeclarationStatementAST *ast) + { + translationUnit()->warning(ast->firstToken(), "ambiguous expression or declaration statement"); + return true; + } +}; + int main(int argc, char *argv[]) { if (getenv("CPLUSPLUS_WITH_NEW_PREPROCESSOR")) @@ -53,7 +80,7 @@ int main(int argc, char *argv[]) int runWithSystemPreprocessor(int argc, char *argv[]) { std::string cmdline; - cmdline += "gcc -E -xc++ -U__BLOCKS__ -D__restrict= -D__extension__="; + cmdline += "gcc -E -xc++ -U__BLOCKS__ -D__restrict= -D__restrict__= -D__extension__= -D__imag__= -D__real__= -D__complex__= -D_Complex= -D__signed=signed"; for (int i = 1; i < argc; ++i) { cmdline += ' '; @@ -117,7 +144,12 @@ void parse(const char *fileName, const char *source, unsigned size) unit.setSource(source, size); unit.parse(); +#if 1 Namespace *globalNamespace = control.newNamespace(0); Bind bind(&unit); bind(unit.ast()->asTranslationUnit(), globalNamespace); + + V v(&unit); + v.accept(unit.ast()); +#endif }