diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 66d7f908e70e861d86ec91ff28ad8d1b40c3d31c..172f50fb4a398572b76dbb7dec9a48d15b5b3eed 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 return true; else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_FLAGS") return true; + else if (size == 12 && macroId.at(0) == 'Q' && macroId == "Q_INTERFACES") + return true; else if (size == 6 && macroId.at(0) == 'S' && macroId == "SIGNAL") return true; else if (size == 4 && macroId.at(0) == 'S' && macroId == "SLOT") diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index f6aebdb688fd103cfb4898f6dbe955b59482393a..6da6f08c65e6ecf72b6c0237070ae3a235e6efe1 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -197,7 +197,7 @@ unsigned QtEnumDeclarationAST::lastToken() const unsigned QtFlagsDeclarationAST::firstToken() const { - return flags_specifier_token + 1; + return flags_specifier_token; } unsigned QtFlagsDeclarationAST::lastToken() const @@ -212,6 +212,43 @@ unsigned QtFlagsDeclarationAST::lastToken() const return flags_specifier_token + 1; } +unsigned QtInterfaceNameAST::firstToken() const +{ + if (interface_name) + return interface_name->firstToken(); + else if (constraint_list) + return constraint_list->firstToken(); + else + return 0; +} + +unsigned QtInterfaceNameAST::lastToken() const +{ + if (constraint_list) + return constraint_list->lastToken(); + else if (interface_name) + return interface_name->lastToken(); + else + return 0; +} + +unsigned QtInterfacesDeclarationAST::firstToken() const +{ + return interfaces_token; +} + +unsigned QtInterfacesDeclarationAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (interface_name_list) + return interface_name_list->lastToken(); + else if (lparen_token) + return lparen_token + 1; + else + return interfaces_token + 1; +} + unsigned ArrayAccessAST::firstToken() const { return lbracket_token; diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index 40147912beea23c51d7d14ad35825810f31075fe..f9f13a0b7ad10d02fe96957b0d6557be58fbc0cf 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -256,6 +256,8 @@ public: virtual PtrOperatorAST *asPtrOperator() { return 0; } virtual QtEnumDeclarationAST *asQtEnumDeclaration() { return 0; } virtual QtFlagsDeclarationAST *asQtFlagsDeclaration() { return 0; } + virtual QtInterfaceNameAST *asQtInterfaceName() { return 0; } + virtual QtInterfacesDeclarationAST *asQtInterfacesDeclaration() { return 0; } virtual QtMemberDeclarationAST *asQtMemberDeclaration() { return 0; } virtual QtMethodAST *asQtMethod() { return 0; } virtual QtPropertyDeclarationAST *asQtPropertyDeclaration() { return 0; } @@ -660,6 +662,46 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +class CPLUSPLUS_EXPORT QtInterfaceNameAST: public AST +{ +public: + NameAST *interface_name; + NameListAST *constraint_list; + +public: + virtual QtInterfaceNameAST *asQtInterfaceName() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual QtInterfaceNameAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CPLUSPLUS_EXPORT QtInterfacesDeclarationAST: public DeclarationAST +{ +public: + unsigned interfaces_token; + unsigned lparen_token; + QtInterfaceNameListAST *interface_name_list; + unsigned rparen_token; + +public: + virtual QtInterfacesDeclarationAST *asQtInterfacesDeclaration() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual QtInterfacesDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + class CPLUSPLUS_EXPORT AsmDefinitionAST: public DeclarationAST { public: diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index f9d45b6fed7706d21058ab4c977a77bdf3dc4bfc..1e58c3f692e6bc58da79f086cbbf6be2889439a8 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -204,6 +204,29 @@ QtFlagsDeclarationAST *QtFlagsDeclarationAST::clone(MemoryPool *pool) const return ast; } +QtInterfaceNameAST *QtInterfaceNameAST::clone(MemoryPool *pool) const +{ + QtInterfaceNameAST *ast = new (pool) QtInterfaceNameAST; + if (interface_name) + ast->interface_name = interface_name->clone(pool); + for (NameListAST *iter = constraint_list, **ast_iter = &ast->constraint_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : 0); + return ast; +} + +QtInterfacesDeclarationAST *QtInterfacesDeclarationAST::clone(MemoryPool *pool) const +{ + QtInterfacesDeclarationAST *ast = new (pool) QtInterfacesDeclarationAST; + ast->interfaces_token = interfaces_token; + ast->lparen_token = lparen_token; + for (QtInterfaceNameListAST *iter = interface_name_list, **ast_iter = &ast->interface_name_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) QtInterfaceNameListAST((iter->value) ? iter->value->clone(pool) : 0); + ast->rparen_token = rparen_token; + return ast; +} + AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const { AsmDefinitionAST *ast = new (pool) AsmDefinitionAST; diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp index 4347c7230b64ba07924d1d34288503328c2a232e..d594b441d2a332e12969e07656243f5b66f445f0 100644 --- a/src/shared/cplusplus/ASTMatch0.cpp +++ b/src/shared/cplusplus/ASTMatch0.cpp @@ -153,6 +153,22 @@ bool QtFlagsDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool QtInterfaceNameAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QtInterfaceNameAST *_other = pattern->asQtInterfaceName()) + return matcher->match(this, _other); + + return false; +} + +bool QtInterfacesDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QtInterfacesDeclarationAST *_other = pattern->asQtInterfacesDeclaration()) + return matcher->match(this, _other); + + return false; +} + bool AsmDefinitionAST::match0(AST *pattern, ASTMatcher *matcher) { if (AsmDefinitionAST *_other = pattern->asAsmDefinition()) diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index c9980d62e227c357e2e132320eedd305a2dead8c..044f7b1f060c9be5175d8b22ce2ea121f9cda5fb 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -313,6 +313,43 @@ bool ASTMatcher::match(QtFlagsDeclarationAST *node, QtFlagsDeclarationAST *patte return true; } +bool ASTMatcher::match(QtInterfaceNameAST *node, QtInterfaceNameAST *pattern) +{ + (void) node; + (void) pattern; + + if (! pattern->interface_name) + pattern->interface_name = node->interface_name; + else if (! AST::match(node->interface_name, pattern->interface_name, this)) + return false; + + if (! pattern->constraint_list) + pattern->constraint_list = node->constraint_list; + else if (! AST::match(node->constraint_list, pattern->constraint_list, this)) + return false; + + return true; +} + +bool ASTMatcher::match(QtInterfacesDeclarationAST *node, QtInterfacesDeclarationAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->interfaces_token = node->interfaces_token; + + pattern->lparen_token = node->lparen_token; + + if (! pattern->interface_name_list) + pattern->interface_name_list = node->interface_name_list; + else if (! AST::match(node->interface_name_list, pattern->interface_name_list, this)) + return false; + + pattern->rparen_token = node->rparen_token; + + return true; +} + bool ASTMatcher::match(AsmDefinitionAST *node, AsmDefinitionAST *pattern) { (void) node; diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h index 7dfeec7c16a31d94eca98b98078511762ab8299c..3de5b736a86233a877b2874c071d79c6a205c259 100644 --- a/src/shared/cplusplus/ASTMatcher.h +++ b/src/shared/cplusplus/ASTMatcher.h @@ -43,6 +43,8 @@ public: virtual bool match(QtPropertyDeclarationAST *node, QtPropertyDeclarationAST *pattern); virtual bool match(QtEnumDeclarationAST *node, QtEnumDeclarationAST *pattern); virtual bool match(QtFlagsDeclarationAST *node, QtFlagsDeclarationAST *pattern); + virtual bool match(QtInterfaceNameAST *node, QtInterfaceNameAST *pattern); + virtual bool match(QtInterfacesDeclarationAST *node, QtInterfacesDeclarationAST *pattern); virtual bool match(ArrayAccessAST *node, ArrayAccessAST *pattern); virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern); virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern); diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index df08727aec7085d553ec830ed41540bdf8fb962a..0e9575240d3d7fdaa5eab4c69a8b9c7d29325457 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -157,6 +157,23 @@ void QtFlagsDeclarationAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void QtInterfaceNameAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(interface_name, visitor); + accept(constraint_list, visitor); + } + visitor->endVisit(this); +} + +void QtInterfacesDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(interface_name_list, visitor); + } + visitor->endVisit(this); +} + void AsmDefinitionAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index bb1bea71092799d087ac2aeead312891d750fb7b..25a9aa27419c1c5385c7bf91ca4d2119337d8e0b 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -204,6 +204,8 @@ public: virtual bool visit(QtMethodAST *) { return true; } virtual bool visit(QtMemberDeclarationAST *) { return true; } virtual bool visit(QtPropertyDeclarationItemAST *) { return true; } + virtual bool visit(QtInterfacesDeclarationAST *) { return true; } + virtual bool visit(QtInterfaceNameAST *) { return true; } // ObjC++ virtual bool visit(ObjCClassDeclarationAST *) { return true; } @@ -334,6 +336,8 @@ public: virtual void endVisit(QtMethodAST *) { } virtual void endVisit(QtMemberDeclarationAST *) { } virtual void endVisit(QtPropertyDeclarationItemAST *) { } + virtual void endVisit(QtInterfacesDeclarationAST *) { } + virtual void endVisit(QtInterfaceNameAST *) { } // ObjC++ virtual void endVisit(ObjCClassDeclarationAST *) { } diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index 5779bdf0d3482a80104952c3401fc63a4bb8e852..d068f1203624031876c527bdf41e070ff7da9d13 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -163,6 +163,8 @@ class PostfixExpressionAST; class PtrOperatorAST; class QtEnumDeclarationAST; class QtFlagsDeclarationAST; +class QtInterfaceNameAST; +class QtInterfacesDeclarationAST; class QtMemberDeclarationAST; class QtMethodAST; class QtPropertyDeclarationAST; @@ -213,6 +215,7 @@ typedef List<PtrOperatorAST *> PtrOperatorListAST; typedef List<SpecifierAST *> SpecifierListAST; typedef List<QtPropertyDeclarationItemAST *> QtPropertyDeclarationItemListAST; typedef List<NameAST *> NameListAST; +typedef List<QtInterfaceNameAST *> QtInterfaceNameListAST; typedef List<ObjCMessageArgumentAST *> ObjCMessageArgumentListAST; typedef List<ObjCSelectorArgumentAST *> ObjCSelectorArgumentListAST; diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp index d42ca3795a4332fab356b37a935218b8c8d32185..7ce723e3cc9d1b51a0084a0ac15ad193f64c1589 100644 --- a/src/shared/cplusplus/Keywords.cpp +++ b/src/shared/cplusplus/Keywords.cpp @@ -1198,7 +1198,7 @@ static inline int classify11(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify12(const char *s, bool) { +static inline int classify12(const char *s, bool q) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'v') { @@ -1224,6 +1224,31 @@ static inline int classify12(const char *s, bool) { } } } + else if (q && s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'I') { + if (s[3] == 'N') { + if (s[4] == 'T') { + if (s[5] == 'E') { + if (s[6] == 'R') { + if (s[7] == 'F') { + if (s[8] == 'A') { + if (s[9] == 'C') { + if (s[10] == 'E') { + if (s[11] == 'S') { + return T_Q_INTERFACES; + } + } + } + } + } + } + } + } + } + } + } + } else if (s[0] == 'd') { if (s[1] == 'y') { if (s[2] == 'n') { diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 93b30251c7c54918b0278ab8a765a6e3edae5a69..95372cbad5befd6e110ea3c45324bcf65fd3ee3c 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -293,6 +293,7 @@ void Parser::skipUntilDeclaration() case T_Q_PROPERTY: case T_Q_ENUMS: case T_Q_FLAGS: + case T_Q_INTERFACES: // Qt function specifiers case T_Q_SIGNAL: @@ -1942,6 +1943,78 @@ bool Parser::parseQtFlags(DeclarationAST *&node) return true; } +// class-specifier ::= +// c++-class-specifier +// q-tag +// q-enums-of-flags +// q-class-info +// q-interfaces +// q-private-slot +// +// declaration ::= +// c++-declaration +// q-declare-interface +// q-declare-metatype +// +// q-tag ::= +// Q_OBJECT +// Q_GADGET +// +// q-enums-or-flags ::= +// (Q_ENUMS | Q_FLAGS) LPAREN name+ RPAREN +// +// q-class-info ::= +// Q_CLASS_INFO LPAREN string-literal COMMA STRING_LITERAL RPAREN +// Q_CLASS_INFO LPAREN string-literal COMMA IDENTIFIER LPAREN STRING_LITERAL RPAREN RPAREN + +// q-interfaces ::= +// Q_INTERFACES LPAREN (name q-constraints)* RPAREN +// +// q-constraints ::= +// (COLON name)* +bool Parser::parseQtInterfaces(DeclarationAST *&node) +{ + DEBUG_THIS_RULE(); + if (LA() != T_Q_INTERFACES) + return false; + + QtInterfacesDeclarationAST *ast = new (_pool) QtInterfacesDeclarationAST; + ast->interfaces_token = consumeToken(); + match(T_LPAREN, &ast->lparen_token); + for (QtInterfaceNameListAST **iter = &ast->interface_name_list; LA() && LA() != T_RPAREN; iter = &(*iter)->next) { + NameAST *name_ast = 0; + if (!parseName(name_ast)) + break; + *iter = new (_pool) QtInterfaceNameListAST; + (*iter)->value = new (_pool) QtInterfaceNameAST; + (*iter)->value->interface_name = name_ast; + for (NameListAST **iter2 = &(*iter)->value->constraint_list; LA() && LA() == T_COLON; iter2 = &(*iter2)->next) { + /*unsigned colon_token =*/ consumeToken(); + NameAST *name_ast2 = 0; + if (!parseName(name_ast2)) + break; + *iter2 = new (_pool) NameListAST; + (*iter2)->value = name_ast2; + } + } + + match(T_RPAREN, &ast->rparen_token); + node = ast; + return true; +} + +// q-private-slot ::= +// Q_PRIVATE_SLOT LPAREN IDENTIFIER (LPAREN RPAREN)? COMMA q-function-declaration RPAREN +// +// q-function-declaration ::= +// decl-specifier-list declarator [+ check for the function-declarator] +// +// q-declare-interface ::= +// Q_DECLARE_INTERFACE LPAREN name COMMA (STRING_LITERAL | IDENTIFIER) RPAREN +// +// q-declare-metatype ::= +// Q_DECLARE_METATYPE LPAREN name RPAREN SEMICOLON? [warning] + bool Parser::parseMemberSpecification(DeclarationAST *&node) { DEBUG_THIS_RULE(); @@ -1971,6 +2044,9 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node) case T_Q_FLAGS: return parseQtFlags(node); + case T_Q_INTERFACES: + return parseQtInterfaces(node); + default: return parseSimpleDeclaration(node, /*acceptStructDeclarator=*/true); } // switch diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index e10be3ac81d70c7742a522be7e3a07c93ceee4f3..1ae857ea81eda225faed5769fc827217cfe32228 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -81,6 +81,7 @@ public: bool parseQtPropertyDeclaration(DeclarationAST *&node); bool parseQtEnumDeclaration(DeclarationAST *&node); bool parseQtFlags(DeclarationAST *&node); + bool parseQtInterfaces(DeclarationAST *&node); bool parseAdditiveExpression(ExpressionAST *&node); bool parseAndExpression(ExpressionAST *&node); bool parseAsmDefinition(DeclarationAST *&node); diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp index 9dfe80b15490c3f8baddaf83adcdce04e8a6be4e..cafce02eacb047eab4e0d9f9d7c75675c9e2e1a3 100644 --- a/src/shared/cplusplus/Token.cpp +++ b/src/shared/cplusplus/Token.cpp @@ -93,7 +93,7 @@ static const char *token_names[] = { ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH"), ("Q_D"), ("Q_Q"), - ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_ENUMS"), ("Q_FLAGS") + ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_INTERFACES"), ("Q_ENUMS"), ("Q_FLAGS") }; Token::Token() : diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h index 7644a31b821e9480194c44e2135b45f2a3a97482..e71d25bf62a3c66c1e42c8ec1cb3598b6e251f48 100644 --- a/src/shared/cplusplus/Token.h +++ b/src/shared/cplusplus/Token.h @@ -240,6 +240,7 @@ enum Kind { T_Q_Q, T_Q_INVOKABLE, T_Q_PROPERTY, + T_Q_INTERFACES, T_Q_ENUMS, T_Q_FLAGS, T_LAST_KEYWORD = T_Q_FLAGS,