diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 6da6f08c65e6ecf72b6c0237070ae3a235e6efe1..752a383a33014ba2a3480908fd19930ca2a4f4b4 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -144,6 +144,42 @@ unsigned AccessDeclarationAST::lastToken() const
     return access_specifier_token + 1;
 }
 
+unsigned QtObjectTagAST::firstToken() const
+{
+    return q_object_token;
+}
+
+unsigned QtObjectTagAST::lastToken() const
+{
+    return q_object_token + 1;
+}
+
+unsigned QtPrivateSlotAST::firstToken() const
+{
+    return q_private_slot_token;
+}
+
+unsigned QtPrivateSlotAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    else if (declarator)
+        return declarator->lastToken();
+    else if (type_specifiers)
+        type_specifiers->lastToken();
+    else if (comma_token)
+        return comma_token + 1;
+    else if (dptr_rparen_token)
+        return dptr_rparen_token + 1;
+    else if (dptr_lparen_token)
+        return dptr_lparen_token + 1;
+    else if (dptr_token)
+        return dptr_token + 1;
+    else if (lparen_token)
+        return lparen_token + 1;
+    return q_private_slot_token + 1;
+}
+
 unsigned QtPropertyDeclarationItemAST::firstToken() const
 {
     return item_name_token;
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index f9f13a0b7ad10d02fe96957b0d6557be58fbc0cf..85040258e268300ce2a08bacfbd66859c63d8a57 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -101,7 +101,7 @@ public:
 
         return lastValue;
     }
-    
+
     _Tp value;
     List *next;
 };
@@ -260,6 +260,8 @@ public:
     virtual QtInterfacesDeclarationAST *asQtInterfacesDeclaration() { return 0; }
     virtual QtMemberDeclarationAST *asQtMemberDeclaration() { return 0; }
     virtual QtMethodAST *asQtMethod() { return 0; }
+    virtual QtObjectTagAST *asQtObjectTag() { return 0; }
+    virtual QtPrivateSlotAST *asQtPrivateSlot() { return 0; }
     virtual QtPropertyDeclarationAST *asQtPropertyDeclaration() { return 0; }
     virtual QtPropertyDeclarationItemAST *asQtPropertyDeclarationItem() { return 0; }
     virtual QualifiedNameAST *asQualifiedName() { return 0; }
@@ -578,6 +580,50 @@ protected:
     virtual bool match0(AST *, ASTMatcher *);
 };
 
+class CPLUSPLUS_EXPORT QtObjectTagAST: public DeclarationAST
+{
+public:
+    unsigned q_object_token;
+
+public:
+    virtual QtObjectTagAST *asQtObjectTag() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtObjectTagAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
+class CPLUSPLUS_EXPORT QtPrivateSlotAST: public DeclarationAST
+{
+public:
+    unsigned q_private_slot_token;
+    unsigned lparen_token;
+    unsigned dptr_token;
+    unsigned dptr_lparen_token;
+    unsigned dptr_rparen_token;
+    unsigned comma_token;
+    SpecifierListAST *type_specifiers;
+    DeclaratorAST *declarator;
+    unsigned rparen_token;
+
+public:
+    virtual QtPrivateSlotAST *asQtPrivateSlot() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual QtPrivateSlotAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
 class QtPropertyDeclarationItemAST: public AST
 {
 public:
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 1e58c3f692e6bc58da79f086cbbf6be2889439a8..7920644c43db556a40e09e1ff51c0285afe99e92 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -155,6 +155,31 @@ AccessDeclarationAST *AccessDeclarationAST::clone(MemoryPool *pool) const
     return ast;
 }
 
+QtObjectTagAST *QtObjectTagAST::clone(MemoryPool *pool) const
+{
+    QtObjectTagAST *ast = new (pool) QtObjectTagAST;
+    ast->q_object_token = q_object_token;
+    return ast;
+}
+
+QtPrivateSlotAST *QtPrivateSlotAST::clone(MemoryPool *pool) const
+{
+    QtPrivateSlotAST *ast = new (pool) QtPrivateSlotAST;
+    ast->q_private_slot_token = q_private_slot_token;
+    ast->lparen_token = lparen_token;
+    ast->dptr_token = dptr_token;
+    ast->dptr_lparen_token = dptr_lparen_token;
+    ast->dptr_rparen_token = dptr_rparen_token;
+    ast->comma_token = comma_token;
+    for (SpecifierListAST *iter = type_specifiers, **ast_iter = &ast->type_specifiers;
+         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
+        *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
+    if (declarator)
+        ast->declarator = declarator->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 QtPropertyDeclarationItemAST *QtPropertyDeclarationItemAST::clone(MemoryPool *pool) const
 {
     QtPropertyDeclarationItemAST *ast = new (pool) QtPropertyDeclarationItemAST;
diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp
index d594b441d2a332e12969e07656243f5b66f445f0..0b97e9c7fa2b27aeeb13e3ddab1678d548bc83a2 100644
--- a/src/shared/cplusplus/ASTMatch0.cpp
+++ b/src/shared/cplusplus/ASTMatch0.cpp
@@ -121,6 +121,22 @@ bool AccessDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
     return false;
 }
 
+bool QtObjectTagAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtObjectTagAST *_other = pattern->asQtObjectTag())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
+bool QtPrivateSlotAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (QtPrivateSlotAST *_other = pattern->asQtPrivateSlot())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
 bool QtPropertyDeclarationItemAST::match0(AST *pattern, ASTMatcher *matcher)
 {
     if (QtPropertyDeclarationItemAST *_other = pattern->asQtPropertyDeclarationItem())
diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp
index 044f7b1f060c9be5175d8b22ce2ea121f9cda5fb..e9734c661fe418b73064fc69fa4b332aaf6b3405 100644
--- a/src/shared/cplusplus/ASTMatcher.cpp
+++ b/src/shared/cplusplus/ASTMatcher.cpp
@@ -231,6 +231,48 @@ bool ASTMatcher::match(AccessDeclarationAST *node, AccessDeclarationAST *pattern
     return true;
 }
 
+bool ASTMatcher::match(QtObjectTagAST *node, QtObjectTagAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->q_object_token = node->q_object_token;
+
+    return true;
+}
+
+bool ASTMatcher::match(QtPrivateSlotAST *node, QtPrivateSlotAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->q_private_slot_token = node->q_private_slot_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    pattern->dptr_token = node->dptr_token;
+
+    pattern->dptr_lparen_token = node->dptr_lparen_token;
+
+    pattern->dptr_rparen_token = node->dptr_rparen_token;
+
+    pattern->comma_token = node->comma_token;
+
+    if (! pattern->type_specifiers)
+        pattern->type_specifiers = node->type_specifiers;
+    else if (! AST::match(node->type_specifiers, pattern->type_specifiers, this))
+        return false;
+
+    if (! pattern->declarator)
+        pattern->declarator = node->declarator;
+    else if (! AST::match(node->declarator, pattern->declarator, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
 bool ASTMatcher::match(QtPropertyDeclarationItemAST *node, QtPropertyDeclarationItemAST *pattern)
 {
     (void) node;
diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h
index 3de5b736a86233a877b2874c071d79c6a205c259..baae1ce874f43e0bcb765933fa54032813a0097e 100644
--- a/src/shared/cplusplus/ASTMatcher.h
+++ b/src/shared/cplusplus/ASTMatcher.h
@@ -40,6 +40,8 @@ public:
     virtual ~ASTMatcher();
 
     virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern);
+    virtual bool match(QtObjectTagAST *node, QtObjectTagAST *pattern);
+    virtual bool match(QtPrivateSlotAST *node, QtPrivateSlotAST *pattern);
     virtual bool match(QtPropertyDeclarationAST *node, QtPropertyDeclarationAST *pattern);
     virtual bool match(QtEnumDeclarationAST *node, QtEnumDeclarationAST *pattern);
     virtual bool match(QtFlagsDeclarationAST *node, QtFlagsDeclarationAST *pattern);
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index 0e9575240d3d7fdaa5eab4c69a8b9c7d29325457..f58974f0168e228cb49c3711e5ba1472d10d60a4 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -123,6 +123,22 @@ void AccessDeclarationAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
+void QtObjectTagAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+    visitor->endVisit(this);
+}
+
+void QtPrivateSlotAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(type_specifiers, visitor);
+        accept(declarator, visitor);
+    }
+    visitor->endVisit(this);
+}
+
 void QtPropertyDeclarationItemAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h
index 25a9aa27419c1c5385c7bf91ca4d2119337d8e0b..4490f11faab5787bbe83c062691d7e22f569870f 100644
--- a/src/shared/cplusplus/ASTVisitor.h
+++ b/src/shared/cplusplus/ASTVisitor.h
@@ -103,6 +103,8 @@ public:
     virtual void postVisit(AST *) {}
 
     virtual bool visit(AccessDeclarationAST *) { return true; }
+    virtual bool visit(QtObjectTagAST *) { return true; }
+    virtual bool visit(QtPrivateSlotAST *) { return true; }
     virtual bool visit(QtPropertyDeclarationAST *) { return true; }
     virtual bool visit(QtEnumDeclarationAST *) { return true; }
     virtual bool visit(QtFlagsDeclarationAST *) { return true; }
@@ -235,6 +237,8 @@ public:
     virtual bool visit(ObjCSynchronizedStatementAST *) { return true; }
 
     virtual void endVisit(AccessDeclarationAST *) { }
+    virtual void endVisit(QtObjectTagAST *) {}
+    virtual void endVisit(QtPrivateSlotAST *) {}
     virtual void endVisit(QtPropertyDeclarationAST *) { }
     virtual void endVisit(QtEnumDeclarationAST *) { }
     virtual void endVisit(QtFlagsDeclarationAST *) { }
diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h
index d068f1203624031876c527bdf41e070ff7da9d13..f8f129acb49fc244954ad76a4c10f2f3e5b6fb8d 100644
--- a/src/shared/cplusplus/ASTfwd.h
+++ b/src/shared/cplusplus/ASTfwd.h
@@ -167,6 +167,8 @@ class QtInterfaceNameAST;
 class QtInterfacesDeclarationAST;
 class QtMemberDeclarationAST;
 class QtMethodAST;
+class QtObjectTagAST;
+class QtPrivateSlotAST;
 class QtPropertyDeclarationAST;
 class QtPropertyDeclarationItemAST;
 class QualifiedNameAST;
diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp
index 7ce723e3cc9d1b51a0084a0ac15ad193f64c1589..0e6beaf06f4a8fa9153f9f9598f1160ee8c9c528 100644
--- a/src/shared/cplusplus/Keywords.cpp
+++ b/src/shared/cplusplus/Keywords.cpp
@@ -912,7 +912,33 @@ static inline int classify8(const char *s, bool q) {
   }
   else if (q && s[0] == 'Q') {
     if (s[1] == '_') {
-      if (s[2] == 'S') {
+      if (s[2] == 'G') {
+        if (s[3] == 'A') {
+          if (s[4] == 'D') {
+            if (s[5] == 'G') {
+              if (s[6] == 'E') {
+                if (s[7] == 'T') {
+                  return T_Q_GADGET;
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'O') {
+        if (s[3] == 'B') {
+          if (s[4] == 'J') {
+            if (s[5] == 'E') {
+              if (s[6] == 'C') {
+                if (s[7] == 'T') {
+                  return T_Q_OBJECT;
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'S') {
         if (s[3] == 'I') {
           if (s[4] == 'G') {
             if (s[5] == 'N') {
@@ -1103,7 +1129,24 @@ static inline int classify10(const char *s, bool q) {
   }
   else if (q && s[0] == 'Q') {
     if (s[1] == '_') {
-      if (s[2] == 'P') {
+      if (s[2] == 'O') {
+        if (s[3] == 'V') {
+          if (s[4] == 'E') {
+            if (s[5] == 'R') {
+              if (s[6] == 'R') {
+                if (s[7] == 'I') {
+                  if (s[8] == 'D') {
+                    if (s[9] == 'E') {
+                      return T_Q_PROPERTY; // Q_OVERRIDE is just an alias for Q_PROPERTY
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (s[2] == 'P') {
         if (s[3] == 'R') {
           if (s[4] == 'O') {
             if (s[5] == 'P') {
@@ -1345,6 +1388,83 @@ static inline int classify16(const char *s, bool) {
   return T_IDENTIFIER;
 }
 
+static inline int classify14(const char *s, bool q) {
+  if (q && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'P') {
+        if (s[3] == 'R') {
+          if (s[4] == 'I') {
+            if (s[5] == 'V') {
+              if (s[6] == 'A') {
+                if (s[7] == 'T') {
+                  if (s[8] == 'E') {
+                    if (s[9] == '_') {
+                      if (s[10] == 'S') {
+                        if (s[11] == 'L') {
+                          if (s[12] == 'O') {
+                            if (s[13] == 'T') {
+                              return T_Q_PRIVATE_SLOT;
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+static inline int classify19(const char *s, bool q) {
+  if (q && s[0] == 'Q') {
+    if (s[1] == '_') {
+      if (s[2] == 'D') {
+        if (s[3] == 'E') {
+          if (s[4] == 'C') {
+            if (s[5] == 'L') {
+              if (s[6] == 'A') {
+                if (s[7] == 'R') {
+                  if (s[8] == 'E') {
+                    if (s[9] == '_') {
+                      if (s[10] == 'I') {
+                        if (s[11] == 'N') {
+                          if (s[12] == 'T') {
+                            if (s[13] == 'E') {
+                              if (s[14] == 'R') {
+                                if (s[15] == 'F') {
+                                  if (s[16] == 'A') {
+                                    if (s[17] == 'C') {
+                                      if (s[18] == 'E') {
+                                        return T_Q_DECLARE_INTERFACE;
+                                      }
+                                    }
+                                  }
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return T_IDENTIFIER;
+}
+
+
 int Lexer::classify(const char *s, int n, bool q) {
   switch (n) {
     case 2: return classify2(s, q);
@@ -1359,7 +1479,9 @@ int Lexer::classify(const char *s, int n, bool q) {
     case 11: return classify11(s, q);
     case 12: return classify12(s, q);
     case 13: return classify13(s, q);
+    case 14: return classify14(s, q);
     case 16: return classify16(s, q);
+    case 19: return classify19(s, q);
     default: return T_IDENTIFIER;
   } // switch
 }
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 95372cbad5befd6e110ea3c45324bcf65fd3ee3c..ce5afdd5faa377280d21ab376d5ba986935e6a89 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -609,6 +609,21 @@ bool Parser::parseDeclaration(DeclarationAST *&node)
     case T_AT_IMPLEMENTATION:
         return parseObjCImplementation(node);
 
+    case T_Q_DECLARE_INTERFACE:
+    {
+        consumeToken();
+        unsigned lparen_token = 0;
+        match(T_LPAREN, &lparen_token);
+        NameAST *name = 0;
+        parseName(name);
+        unsigned comma_token = 0;
+        match(T_COMMA, &comma_token);
+        unsigned string_literal = 0;
+        match(T_STRING_LITERAL, &string_literal);
+        unsigned rparen_token = 0;
+        match(T_RPAREN, &rparen_token);
+    }   return true;
+
     case T_AT_END:
         // TODO: should this be done here, or higher-up?
         _translationUnit->error(cursor(), "skip stray token `%s'", tok().spell());
@@ -2019,6 +2034,32 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node)
 {
     DEBUG_THIS_RULE();
     switch (LA()) {
+    case T_Q_OBJECT:
+    case T_Q_GADGET:
+    {
+        QtObjectTagAST *ast = new (_pool) QtObjectTagAST;
+        ast->q_object_token = consumeToken();
+        node = ast;
+        return true;
+    }
+
+    case T_Q_PRIVATE_SLOT:
+    {
+        QtPrivateSlotAST *ast = new (_pool) QtPrivateSlotAST;
+        ast->q_private_slot_token = consumeToken();
+        match(T_LPAREN, &ast->lparen_token);
+        match(T_IDENTIFIER, &ast->dptr_token);
+        if (LA() == T_LPAREN) {
+            ast->dptr_lparen_token = consumeToken();
+            match(T_RPAREN, &ast->dptr_rparen_token);
+        }
+        match(T_COMMA, &ast->comma_token);
+        parseTypeSpecifier(ast->type_specifiers);
+        parseDeclarator(ast->declarator);
+        match(T_RPAREN, &ast->rparen_token);
+        node = ast;
+    }   return true;
+
     case T_SEMICOLON:
         return parseEmptyDeclaration(node);
 
diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp
index cafce02eacb047eab4e0d9f9d7c75675c9e2e1a3..2bb8763e66fa3265fb95f25aecd2cf48be154913 100644
--- a/src/shared/cplusplus/Token.cpp
+++ b/src/shared/cplusplus/Token.cpp
@@ -91,9 +91,12 @@ static const char *token_names[] = {
     ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"),
     ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"),
 
+    // Qt keywords
     ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"),
     ("Q_FOREACH"), ("Q_D"), ("Q_Q"),
-    ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_INTERFACES"), ("Q_ENUMS"), ("Q_FLAGS")
+    ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_INTERFACES"), ("Q_ENUMS"), ("Q_FLAGS"),
+    ("Q_PRIVATE_SLOT"), ("Q_DECLARE_INTERFACE"), ("Q_OBJECT"), ("Q_GADGET"),
+
 };
 
 Token::Token() :
diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h
index e71d25bf62a3c66c1e42c8ec1cb3598b6e251f48..2c858551549441087099c3b8f4f96328a9ba6d2b 100644
--- a/src/shared/cplusplus/Token.h
+++ b/src/shared/cplusplus/Token.h
@@ -243,7 +243,11 @@ enum Kind {
     T_Q_INTERFACES,
     T_Q_ENUMS,
     T_Q_FLAGS,
-    T_LAST_KEYWORD = T_Q_FLAGS,
+    T_Q_PRIVATE_SLOT,
+    T_Q_DECLARE_INTERFACE,
+    T_Q_OBJECT,
+    T_Q_GADGET,
+    T_LAST_KEYWORD = T_Q_GADGET,
 
     // aliases
     T_OR = T_PIPE_PIPE,