diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 372926f59755cb51d82c8bca939498362830d22a..c614daf45eb025666811992997880cbac7ef1813 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1421,6 +1421,8 @@ bool Preprocessor::isQtReservedWord(const QByteArray ¯oId) const const int size = macroId.size(); if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_SIGNALS") return true; + else if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_FOREACH") + return true; else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_SLOTS") return true; else if (size == 8 && macroId.at(0) == 'Q' && macroId == "Q_SIGNAL") diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index c809f6e1d02dd10a7f2231a674a42f742c4b8611..dc6a50567751613fbad3f63d3dc0c2dec1bd757f 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -874,6 +874,24 @@ unsigned ExpressionStatementAST::lastToken() const return 0; } +unsigned ForeachStatementAST::firstToken() const +{ + return foreach_token; +} + +unsigned ForeachStatementAST::lastToken() const +{ + if (statement) + return statement->lastToken(); + else if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (comma_token) + return comma_token + 1; + + return foreach_token + 1; +} unsigned ForStatementAST::firstToken() const { diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index f345fd76b0cadfe485310c0acedb4c6c2ad47454..d22735eeb145b23c01098a7d1e7ac67b450d8d39 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -131,6 +131,7 @@ public: virtual ExpressionListAST *asExpressionList() { return 0; } virtual ExpressionOrDeclarationStatementAST *asExpressionOrDeclarationStatement() { return 0; } virtual ExpressionStatementAST *asExpressionStatement() { return 0; } + virtual ForeachStatementAST *asForeachStatement() { return 0; } virtual ForStatementAST *asForStatement() { return 0; } virtual FunctionDeclaratorAST *asFunctionDeclarator() { return 0; } virtual FunctionDefinitionAST *asFunctionDefinition() { return 0; } @@ -1135,6 +1136,37 @@ protected: virtual void accept0(ASTVisitor *visitor); }; +class CPLUSPLUS_EXPORT ForeachStatementAST: public StatementAST +{ +public: + unsigned foreach_token; + unsigned lparen_token; + // declaration + SpecifierAST *type_specifiers; + DeclaratorAST *declarator; + // or an expression + ExpressionAST *initializer; + unsigned comma_token; + ExpressionAST *expression; + unsigned rparen_token; + StatementAST *statement; + +public: // annotations + Block *symbol; + +public: + virtual ForeachStatementAST *asForeachStatement() + { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ForeachStatementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + class CPLUSPLUS_EXPORT ForStatementAST: public StatementAST { public: diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index c3eb1ab40fa487778aec152b6c39dd1c31cf7f34..2e446c89ef1274f4542c053d17aeb7e89b569e68 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -514,6 +514,23 @@ FunctionDefinitionAST *FunctionDefinitionAST::clone(MemoryPool *pool) const return ast; } +ForeachStatementAST *ForeachStatementAST::clone(MemoryPool *pool) const +{ + ForeachStatementAST *ast = new (pool) ForeachStatementAST; + // copy StatementAST + // copy ForeachStatementAST + ast->foreach_token = foreach_token; + ast->lparen_token = lparen_token; + if (type_specifiers) ast->type_specifiers = type_specifiers->clone(pool); + if (declarator) ast->declarator = declarator->clone(pool); + if (initializer) ast->initializer = initializer->clone(pool); + ast->comma_token = comma_token; + if (expression) ast->expression = expression->clone(pool); + ast->rparen_token = rparen_token; + if (statement) ast->statement = statement->clone(pool); + return ast; +} + ForStatementAST *ForStatementAST::clone(MemoryPool *pool) const { ForStatementAST *ast = new (pool) ForStatementAST; diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index c85ce397078542fc73696161b92d78927de94fb7..1673577474f4a8793b613287f4e2d9e74de6fdc6 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -474,6 +474,21 @@ void FunctionDefinitionAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void ForeachStatementAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + // visit ForeachStatementAST + for (SpecifierAST *it = type_specifiers; it; it = it->next) + accept(it, visitor); + accept(declarator, visitor); + accept(initializer, visitor); + accept(expression, visitor); + accept(statement, visitor); + // visit StatementAST + } + visitor->endVisit(this); +} + void ForStatementAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index 45c8d89efc708e7f19abc0421c6b8b17669d1f7d..caa93e5e1b82572c87f90c818fb8a7a144bf1bdc 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -134,6 +134,7 @@ public: virtual bool visit(ExpressionListAST *) { return true; } virtual bool visit(ExpressionOrDeclarationStatementAST *) { return true; } virtual bool visit(ExpressionStatementAST *) { return true; } + virtual bool visit(ForeachStatementAST *) { return true; } virtual bool visit(ForStatementAST *) { return true; } virtual bool visit(FunctionDeclaratorAST *) { return true; } virtual bool visit(FunctionDefinitionAST *) { return true; } @@ -242,6 +243,7 @@ public: virtual void endVisit(ExpressionListAST *) { } virtual void endVisit(ExpressionOrDeclarationStatementAST *) { } virtual void endVisit(ExpressionStatementAST *) { } + virtual void endVisit(ForeachStatementAST *) { } virtual void endVisit(ForStatementAST *) { } virtual void endVisit(FunctionDeclaratorAST *) { } virtual void endVisit(FunctionDefinitionAST *) { } diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index 0f4d9581bfb9404a34cea61cace67d94e776e171..ee5f8e876ffaf2b961439f959b7bb4667350c65c 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -101,6 +101,7 @@ class ExpressionAST; class ExpressionListAST; class ExpressionOrDeclarationStatementAST; class ExpressionStatementAST; +class ForeachStatementAST; class ForStatementAST; class FunctionDeclaratorAST; class FunctionDefinitionAST; diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 038d70b9a48a9dff38726cba7a748dc98ea2eb2f..1bd8086cdbc6fdb5d2d3914f7186cb9938d357ba 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -251,7 +251,7 @@ bool CheckDeclaration::visit(AccessDeclarationAST *ast) semantic()->switchVisibility(visibility); if (ast->slots_token) semantic()->switchMethodKey(Function::SlotMethod); - else if (accessSpecifier == T_SIGNALS) + else if (accessSpecifier == T_Q_SIGNALS) semantic()->switchMethodKey(Function::SignalMethod); else semantic()->switchMethodKey(Function::NormalMethod); diff --git a/src/shared/cplusplus/CheckStatement.cpp b/src/shared/cplusplus/CheckStatement.cpp index 0d7bced86ecc3acd65bae7dca0c8be84065124b8..c93eca0492de9712e2246617f542c89a1e1bff42 100644 --- a/src/shared/cplusplus/CheckStatement.cpp +++ b/src/shared/cplusplus/CheckStatement.cpp @@ -141,6 +141,35 @@ bool CheckStatement::visit(ExpressionStatementAST *ast) return false; } +bool CheckStatement::visit(ForeachStatementAST *ast) +{ + Block *block = control()->newBlock(ast->foreach_token); + block->setStartOffset(tokenAt(ast->firstToken()).offset); + block->setEndOffset(tokenAt(ast->lastToken()).offset); + ast->symbol = block; + _scope->enterSymbol(block); + Scope *previousScope = switchScope(block->members()); + if (ast->type_specifiers && ast->declarator) { + FullySpecifiedType ty = semantic()->check(ast->type_specifiers, _scope); + Name *name = 0; + ty = semantic()->check(ast->declarator, ty, _scope, &name); + unsigned location = ast->declarator->firstToken(); + if (CoreDeclaratorAST *core_declarator = ast->declarator->core_declarator) + location = core_declarator->firstToken(); + Declaration *decl = control()->newDeclaration(location, name); + decl->setType(ty); + _scope->enterSymbol(decl); + } else { + FullySpecifiedType exprTy = semantic()->check(ast->initializer, _scope); + (void) exprTy; + } + + FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + semantic()->check(ast->statement, _scope); + (void) switchScope(previousScope); + return false; +} + bool CheckStatement::visit(ForStatementAST *ast) { Block *block = control()->newBlock(ast->for_token); diff --git a/src/shared/cplusplus/CheckStatement.h b/src/shared/cplusplus/CheckStatement.h index 59b74b136351a7f3a17e4583379eb2ad59870697..baa2bdccf393e823ce98d42421326a7f68a702c0 100644 --- a/src/shared/cplusplus/CheckStatement.h +++ b/src/shared/cplusplus/CheckStatement.h @@ -75,6 +75,7 @@ protected: virtual bool visit(DoStatementAST *ast); virtual bool visit(ExpressionOrDeclarationStatementAST *ast); virtual bool visit(ExpressionStatementAST *ast); + virtual bool visit(ForeachStatementAST *ast); virtual bool visit(ForStatementAST *ast); virtual bool visit(IfStatementAST *ast); virtual bool visit(LabeledStatementAST *ast); diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h index b06063d4f529418fb20d43cb2fa8c80b1eb8d24a..8b4f09afffb829548474eebab0af54acbec74362 100644 --- a/src/shared/cplusplus/Control.h +++ b/src/shared/cplusplus/Control.h @@ -115,7 +115,7 @@ public: NamedType *namedType(Name *name); /// Creates a new Declaration symbol. - Declaration *newDeclaration(unsigned sourceLocation, Name *name = 0); + Declaration *newDeclaration(unsigned sourceLocation, Name *name); /// Creates a new Argument symbol. Argument *newArgument(unsigned sourceLocation, Name *name = 0); diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp index e1b605668a0f75af8849b158cb87c86fb1892bce..e26244a0af72c48e637d7773acf2f2f74d17c4dc 100644 --- a/src/shared/cplusplus/Keywords.cpp +++ b/src/shared/cplusplus/Keywords.cpp @@ -297,7 +297,7 @@ static inline int classify5(const char *s, bool q) { if (s[2] == 'o') { if (s[3] == 't') { if (s[4] == 's') { - return T_SLOTS; + return T_Q_SLOTS; } } } @@ -627,7 +627,7 @@ static inline int classify7(const char *s, bool q) { if (s[4] == 'a') { if (s[5] == 'l') { if (s[6] == 's') { - return T_SIGNALS; + return T_Q_SIGNALS; } } } @@ -687,7 +687,7 @@ static inline int classify7(const char *s, bool q) { if (s[4] == 'O') { if (s[5] == 'T') { if (s[6] == 'S') { - return T_SLOTS; + return T_Q_SLOTS; } } } @@ -950,7 +950,21 @@ static inline int classify9(const char *s, bool q) { if (s[6] == 'A') { if (s[7] == 'L') { if (s[8] == 'S') { - return T_SIGNALS; + return T_Q_SIGNALS; + } + } + } + } + } + } + } else if (s[2] == 'F') { + if (s[3] == 'O') { + if (s[4] == 'R') { + if (s[5] == 'E') { + if (s[6] == 'A') { + if (s[7] == 'C') { + if (s[8] == 'H') { + return T_Q_FOREACH; } } } diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 08266e9f79db0daa607ab611f3fd4377b6d7b464..dba11df71302e09b1ab1a91606eaa96eb6537687 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -1464,11 +1464,11 @@ bool Parser::parseAccessSpecifier(SpecifierAST *&node) bool Parser::parseAccessDeclaration(DeclarationAST *&node) { - if (LA() == T_PUBLIC || LA() == T_PROTECTED || LA() == T_PRIVATE || LA() == T_SIGNALS) { - bool isSignals = LA() == T_SIGNALS; + if (LA() == T_PUBLIC || LA() == T_PROTECTED || LA() == T_PRIVATE || LA() == T_Q_SIGNALS) { + bool isSignals = LA() == T_Q_SIGNALS; AccessDeclarationAST *ast = new (_pool) AccessDeclarationAST; ast->access_specifier_token = consumeToken(); - if (! isSignals && LA() == T_SLOTS) + if (! isSignals && LA() == T_Q_SLOTS) ast->slots_token = consumeToken(); match(T_COLON, &ast->colon_token); node = ast; @@ -1489,7 +1489,7 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node) case T_TEMPLATE: return parseTemplateDeclaration(node); - case T_SIGNALS: + case T_Q_SIGNALS: case T_PUBLIC: case T_PROTECTED: case T_PRIVATE: @@ -1861,6 +1861,9 @@ bool Parser::parseStatement(StatementAST *&node) case T_DO: return parseDoStatement(node); + case T_Q_FOREACH: + return parseForeachStatement(node); + case T_FOR: return parseForStatement(node); @@ -2108,6 +2111,41 @@ bool Parser::parseDoStatement(StatementAST *&node) return false; } +bool Parser::parseForeachStatement(StatementAST *&node) +{ + if (LA() == T_Q_FOREACH) { + ForeachStatementAST *ast = new (_pool) ForeachStatementAST; + ast->foreach_token = consumeToken(); + match(T_LPAREN, &ast->lparen_token); + + unsigned startOfTypeSpecifier = cursor(); + bool blocked = blockErrors(true); + + if (parseTypeSpecifier(ast->type_specifiers)) + parseDeclarator(ast->declarator); + + if (! ast->type_specifiers || ! ast->declarator) { + ast->type_specifiers = 0; + ast->declarator = 0; + + blockErrors(blocked); + rewind(startOfTypeSpecifier); + parseExpression(ast->expression); + } + + blockErrors(blocked); + + match(T_COMMA, &ast->comma_token); + parseExpression(ast->expression); + match(T_RPAREN, &ast->rparen_token); + parseStatement(ast->statement); + + node = ast; + return true; + } + return false; +} + bool Parser::parseForStatement(StatementAST *&node) { if (LA() == T_FOR) { diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index 330bb84b3d761e6548bef0fcaf3e9fa652137c31..c5515b05ec0107db849b94b9f154cbcccfe14c72 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -121,6 +121,7 @@ public: bool parseExpressionOrDeclarationStatement(StatementAST *&node); bool parseExpressionStatement(StatementAST *&node); bool parseForInitStatement(StatementAST *&node); + bool parseForeachStatement(StatementAST *&node); bool parseForStatement(StatementAST *&node); bool parseFunctionBody(StatementAST *&node); bool parseIfStatement(StatementAST *&node); diff --git a/src/shared/cplusplus/Semantic.cpp b/src/shared/cplusplus/Semantic.cpp index 9e7108bbc54f71a218a442446ef5615de6a24a7b..6f44072302e52b0280bd1962a56b982f88df51ae 100644 --- a/src/shared/cplusplus/Semantic.cpp +++ b/src/shared/cplusplus/Semantic.cpp @@ -179,7 +179,7 @@ int Semantic::visibilityForAccessSpecifier(int tokenKind) const return Symbol::Protected; case T_PRIVATE: return Symbol::Private; - case T_SIGNALS: + case T_Q_SIGNALS: return Symbol::Protected; default: return Symbol::Public; diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h index 660e91e4b67e08645b483dfb6e35650df99d6548..6774dba3361d8528a0cfa917c5a7b1d4455ca845 100644 --- a/src/shared/cplusplus/Token.h +++ b/src/shared/cplusplus/Token.h @@ -234,10 +234,11 @@ enum Kind { T_SLOT, T_Q_SIGNAL, T_Q_SLOT, - T_SIGNALS, - T_SLOTS, + T_Q_SIGNALS, + T_Q_SLOTS, + T_Q_FOREACH, - T_LAST_KEYWORD = T_SLOTS, + T_LAST_KEYWORD = T_Q_FOREACH, // aliases T_OR = T_PIPE_PIPE,