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 &macroId) 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,