diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.cpp b/src/libs/cplusplus/CheckUndefinedSymbols.cpp index d6d4cc6ee8bc72b2aa4742ec6f2c50514966530a..bd3cba0a36d6af2216e113a18d2cce94fbce5862 100644 --- a/src/libs/cplusplus/CheckUndefinedSymbols.cpp +++ b/src/libs/cplusplus/CheckUndefinedSymbols.cpp @@ -539,3 +539,48 @@ bool CheckUndefinedSymbols::visit(ObjCPropertyDeclarationAST *ast) return false; } + +bool CheckUndefinedSymbols::visit(QtDeclareFlagsDeclarationAST *ast) +{ + // ### check flags name too? + + if (ast->enum_name && ast->enum_name->name) { + const Identifier *enumId = ast->enum_name->name->identifier(); + if (!isType(enumId)) // ### we're only checking if the enum name is known as a type name, not as an *enum*. + translationUnit()->warning(ast->enum_name->firstToken(), + "unknown enum '%s'", + enumId->chars()); + } + return false; +} + +bool CheckUndefinedSymbols::visit(QtEnumDeclarationAST *ast) +{ + for (NameListAST *iter = ast->enumerator_list; iter; iter = iter->next) { + if (! iter->value) + continue; + + if (SimpleNameAST *enumName = iter->value->asSimpleName()) { + if (enumName->name) { + const Identifier *enumId = enumName->name->identifier(); + if (!isType(enumId))// ### we're only checking if the enum name is known as a type name, not as an *enum*. + translationUnit()->warning(enumName->firstToken(), + "unknown enum '%s'", + enumId->chars()); + } + } + } + return false; +} + +bool CheckUndefinedSymbols::visit(QtFlagsDeclarationAST *) +{ + // ### TODO + return false; +} + +bool CheckUndefinedSymbols::visit(QtPropertyDeclarationAST *) +{ + // ### TODO + return false; +} diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.h b/src/libs/cplusplus/CheckUndefinedSymbols.h index c8569bd21033dcdf2278c1b8dc006209694be0f3..dc7aa79dc36e5794a817c735aea467acab383e0e 100644 --- a/src/libs/cplusplus/CheckUndefinedSymbols.h +++ b/src/libs/cplusplus/CheckUndefinedSymbols.h @@ -98,6 +98,11 @@ protected: virtual bool visit(ObjCProtocolRefsAST *ast); virtual bool visit(ObjCPropertyDeclarationAST *ast); + virtual bool visit(QtDeclareFlagsDeclarationAST *ast); + virtual bool visit(QtEnumDeclarationAST *ast); + virtual bool visit(QtFlagsDeclarationAST *ast); + virtual bool visit(QtPropertyDeclarationAST *ast); + private: Document::Ptr _doc; NamespaceBindingPtr _globalNamespaceBinding; diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index a5f910e5c771f68c7ff9a5bfbe058a5d2ee90bb7..e7824f9393ff3f5fdb48b4e78054445bc8eef599 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -570,7 +570,7 @@ public: unsigned property_specifier_token; unsigned lparen_token; ExpressionAST *type_id; - SimpleNameAST *type_name; + SimpleNameAST *property_name; unsigned read_token; SimpleNameAST *read_function; unsigned write_token; diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index 8fadf080ab352ff0d064f76bbf9249f05f808bb9..68b907cdcfcb68b973cfe34748e8d13bdf0a6caf 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -145,8 +145,8 @@ QtPropertyDeclarationAST *QtPropertyDeclarationAST::clone(MemoryPool *pool) cons ast->lparen_token = lparen_token; if (type_id) ast->type_id = type_id->clone(pool); - if (type_name) - ast->type_name = type_name->clone(pool); + if (property_name) + ast->property_name = property_name->clone(pool); ast->read_token = read_token; if (read_function) ast->read_function = read_function->clone(pool); diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index 75ff5eceb8c997c38e49739b22b14473ec41a703..0ec34db4747406c56331bf07047f71844517f402 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -220,9 +220,9 @@ bool ASTMatcher::match(QtPropertyDeclarationAST *node, QtPropertyDeclarationAST else if (! AST::match(node->type_id, pattern->type_id, this)) return false; - if (! pattern->type_name) - pattern->type_name = node->type_name; - else if (! AST::match(node->type_name, pattern->type_name, this)) + if (! pattern->property_name) + pattern->property_name = node->property_name; + else if (! AST::match(node->property_name, pattern->property_name, this)) return false; pattern->read_token = node->read_token; diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index e37c96493959a3bbd107ffe0dd2b7693a3142e84..430f60679c8f896ec8b31c4e97917aaf8d8b9a43 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -112,7 +112,7 @@ void QtPropertyDeclarationAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { accept(type_id, visitor); - accept(type_name, visitor); + accept(property_name, visitor); accept(read_function, visitor); accept(write_function, visitor); accept(reset_function, visitor); diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h index f60036229432c0d98afc9acaf7d212e2cef8e472..836257e04f00f46a068f7032b2c0112c7eca5c38 100644 --- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h +++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h @@ -60,11 +60,7 @@ # elif defined(CPLUSPLUS_BUILD_STATIC_LIB) # define CPLUSPLUS_EXPORT # else -# ifdef ICHECK_BUILD -# define CPLUSPLUS_EXPORT -# else -# define CPLUSPLUS_EXPORT Q_DECL_IMPORT -# endif +# define CPLUSPLUS_EXPORT Q_DECL_IMPORT # endif #else # define CPLUSPLUS_EXPORT diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 7a6e07ce971ec5d1ba420281ee7a99a2530cdf23..b5c402e31426b8f35b1f72aed447d883f3db4986 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -170,9 +170,7 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) const bool isQ_SLOT = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT; const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL; -#ifdef ICHECK_BUILD const bool isQ_INVOKABLE = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_INVOKABLE; -#endif List<Declaration *> **decl_it = &ast->symbols; for (DeclaratorListAST *it = ast->declarator_list; it; it = it->next) { @@ -199,10 +197,8 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) fun->setMethodKey(Function::SignalMethod); else if (isQ_SLOT) fun->setMethodKey(Function::SlotMethod); -#ifdef ICHECK_BUILD else if (isQ_INVOKABLE) - fun->setInvokable(true); -#endif + fun->setMethodKey(Function::InvokableMethod); fun->setVisibility(semantic()->currentVisibility()); } else if (semantic()->currentMethodKey() != Function::NormalMethod) { translationUnit()->warning(ast->firstToken(), @@ -266,28 +262,6 @@ bool CheckDeclaration::visit(AccessDeclarationAST *ast) return false; } -#ifdef ICHECK_BUILD -bool CheckDeclaration::visit(QPropertyDeclarationAST *) -{ - return false; -} - -bool CheckDeclaration::visit(QEnumDeclarationAST *) -{ - return false; -} - -bool CheckDeclaration::visit(QFlagsDeclarationAST *) -{ - return false; -} - -bool CheckDeclaration::visit(QDeclareFlagsDeclarationAST *) -{ - return false; -} -#endif - bool CheckDeclaration::visit(AsmDefinitionAST *) { return false; @@ -827,3 +801,43 @@ bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast) return false; } + +bool CheckDeclaration::visit(QtDeclareFlagsDeclarationAST *ast) +{ + if (ast->flags_name) + semantic()->check(ast->flags_name, _scope); + if (ast->enum_name) + semantic()->check(ast->enum_name, _scope); + return false; +} + +bool CheckDeclaration::visit(QtEnumDeclarationAST *ast) +{ + for (NameListAST *iter = ast->enumerator_list; iter; iter = iter->next) + semantic()->check(iter->value, _scope); + return false; +} + +bool CheckDeclaration::visit(QtFlagsDeclarationAST *ast) +{ + for (NameListAST *iter = ast->flag_enums_list; iter; iter = iter->next) + semantic()->check(iter->value, _scope); + return false; +} + +bool CheckDeclaration::visit(QtPropertyDeclarationAST *ast) +{ + if (ast->type_id) + semantic()->check(ast->type_id, _scope); + if (ast->property_name) + semantic()->check(ast->property_name, _scope); + if (ast->read_function) + semantic()->check(ast->read_function, _scope); + if (ast->write_function) + semantic()->check(ast->write_function, _scope); + if (ast->reset_function) + semantic()->check(ast->reset_function, _scope); + if (ast->notify_function) + semantic()->check(ast->notify_function, _scope); + return false; +} diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h index 0090a1d6708f608fd25b432a9af09e59d307995f..03661bc68e76e64f530b7ce5e55932e82b8ed7ca 100644 --- a/src/shared/cplusplus/CheckDeclaration.h +++ b/src/shared/cplusplus/CheckDeclaration.h @@ -77,12 +77,10 @@ protected: virtual bool visit(SimpleDeclarationAST *ast); virtual bool visit(EmptyDeclarationAST *ast); virtual bool visit(AccessDeclarationAST *ast); -#ifdef ICHECK_BUILD - virtual bool visit(QPropertyDeclarationAST *ast); - virtual bool visit(QEnumDeclarationAST *ast); - virtual bool visit(QFlagsDeclarationAST *ast); - virtual bool visit(QDeclareFlagsDeclarationAST *ast); -#endif + virtual bool visit(QtPropertyDeclarationAST *ast); + virtual bool visit(QtEnumDeclarationAST *ast); + virtual bool visit(QtFlagsDeclarationAST *ast); + virtual bool visit(QtDeclareFlagsDeclarationAST *ast); virtual bool visit(AsmDefinitionAST *ast); virtual bool visit(ExceptionDeclarationAST *ast); virtual bool visit(FunctionDefinitionAST *ast); diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 33f7660129b5ebd07d6339b507a8a889cb949188..9c504f0f546553c319174b83213e2e6c37f17923 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -1792,8 +1792,8 @@ bool Parser::parseQtPropertyDeclaration(DeclarationAST *&node) if (LA() == T_LPAREN) { ast->lparen_token = consumeToken(); parseTypeId(ast->type_id); - ast->type_name = new (_pool) SimpleNameAST; - match(T_IDENTIFIER, &ast->type_name->identifier_token); + ast->property_name = new (_pool) SimpleNameAST; + match(T_IDENTIFIER, &ast->property_name->identifier_token); while (true) { if (LA() == T_RPAREN) { @@ -1963,6 +1963,7 @@ bool Parser::parseQtDeclareFlags(DeclarationAST *&node) ast->flags_name = new (_pool) SimpleNameAST; match(T_IDENTIFIER, &ast->flags_name->identifier_token); match(T_COMMA, &ast->comma_token); + ast->enum_name = new (_pool) SimpleNameAST; match(T_IDENTIFIER, &ast->enum_name->identifier_token); match(T_RPAREN, &ast->rparen_token); node = ast; @@ -1995,13 +1996,11 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node) case T_Q_ENUMS: return parseQtEnumDeclaration(node); -#ifdef ICHECK_BUILD case T_Q_FLAGS: - return parseQFlags(node); + return parseQtFlags(node); case T_Q_DECLARE_FLAGS: - return parseQDeclareFlags(node); -#endif + return parseQtDeclareFlags(node); default: return parseSimpleDeclaration(node, /*acceptStructDeclarator=*/true); diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp index ca20980d999f7d0939b742289cc84158b9af8f43..1b880dcf6ecc31310bf5d52173cf1a3c6d77ecd2 100644 --- a/src/shared/cplusplus/Symbols.cpp +++ b/src/shared/cplusplus/Symbols.cpp @@ -353,16 +353,6 @@ bool Function::isPureVirtual() const void Function::setPureVirtual(bool isPureVirtual) { f._isPureVirtual = isPureVirtual; } -#ifdef ICHECK_BUILD - -bool Function::isInvokable() const -{ return f._isInvokable == 1; } - -void Function::setInvokable(bool isInvokable) -{ f._isInvokable = isInvokable; } - -#endif - bool Function::isAmbiguous() const { return f._isAmbiguous; } diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h index ab8eb8b3a16f2ebcd6bf73781e0c51f568867ea6..46ee58ff9263cf98cf37d1e296418c4944c0cf35 100644 --- a/src/shared/cplusplus/Symbols.h +++ b/src/shared/cplusplus/Symbols.h @@ -303,7 +303,8 @@ public: enum MethodKey { NormalMethod, SlotMethod, - SignalMethod + SignalMethod, + InvokableMethod }; public: @@ -351,11 +352,7 @@ public: void setPureVirtual(bool isPureVirtual); #ifdef ICHECK_BUILD - - bool isInvokable() const; - void setInvokable(bool isInvokable); bool isEqualTo(const Function* fct, bool ignoreName = false) const; - #endif // Symbol's interface @@ -395,9 +392,6 @@ private: unsigned _isVolatile: 1; unsigned _isAmbiguous: 1; unsigned _methodKey: 3; -#ifdef ICHECK_BUILD - unsigned _isInvokable: 1; -#endif }; union { unsigned _flags; diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp index a0d1e38d784acb45fd52f73b83cc216ae513a928..f071d21d875ea230e28bfd26ae256dc54ff7e784 100644 --- a/src/shared/cplusplus/Token.cpp +++ b/src/shared/cplusplus/Token.cpp @@ -93,9 +93,7 @@ static const char *token_names[] = { ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH"), ("Q_D"), ("Q_Q"), -#ifdef ICHECK_BUILD ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_ENUMS"), ("Q_FLAGS"), ("Q_DECLARE_FLAGS") -#endif }; Token::Token() : diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index b23bd76eea795b0ccd72843a68df92a718a49296..14e82b6e8b025ae7cbf988d0db0055638bbdac35 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -19,19 +19,21 @@ public: TranslationUnit *parse(const QByteArray &source, TranslationUnit::ParseMode mode, - bool blockErrors = false) + bool blockErrors = false, + bool qtMocRun = false) { const StringLiteral *fileId = control.findOrInsertStringLiteral("<stdin>"); TranslationUnit *unit = new TranslationUnit(&control, fileId); unit->setObjCEnabled(true); + unit->setQtMocRunEnabled(qtMocRun); unit->setSource(source.constData(), source.length()); unit->blockErrors(blockErrors); unit->parse(mode); return unit; } - TranslationUnit *parseDeclaration(const QByteArray &source, bool blockErrors = false) - { return parse(source, TranslationUnit::ParseDeclaration, blockErrors); } + TranslationUnit *parseDeclaration(const QByteArray &source, bool blockErrors = false, bool qtMocRun = false) + { return parse(source, TranslationUnit::ParseDeclaration, blockErrors, qtMocRun); } TranslationUnit *parseExpression(const QByteArray &source) { return parse(source, TranslationUnit::ParseExpression); } @@ -83,6 +85,9 @@ private slots: void array_access_with_nested_expression(); void objc_msg_send_expression(); void objc_msg_send_expression_without_selector(); + + // Qt "keywords" + void q_enum_1(); }; void tst_AST::gcc_attributes_1() @@ -977,5 +982,37 @@ void tst_AST::objc_msg_send_expression_without_selector() QVERIFY(!bodyStatements->next->value->asReturnStatement()->expression); } +void tst_AST::q_enum_1() +{ + QSharedPointer<TranslationUnit> unit(parseDeclaration("\n" + "class Tst {\n" + "Q_ENUMS(e)\n" + "public:\n" + "enum e { x, y };\n" + "};\n", + false, true)); + QVERIFY(unit->ast()); + SimpleDeclarationAST *tstDecl = unit->ast()->asSimpleDeclaration(); + QVERIFY(tstDecl); + QVERIFY(! tstDecl->declarator_list); + QVERIFY(tstDecl->decl_specifier_list); + QVERIFY(tstDecl->decl_specifier_list->value); + QVERIFY(! tstDecl->decl_specifier_list->next); + ClassSpecifierAST *tst = tstDecl->decl_specifier_list->value->asClassSpecifier(); + QVERIFY(tst); + + QVERIFY(tst->member_specifier_list); + QVERIFY(tst->member_specifier_list->value); + QtEnumDeclarationAST *qtEnum = tst->member_specifier_list->value->asQtEnumDeclaration(); + QVERIFY(qtEnum); + QVERIFY(qtEnum->enumerator_list); + QVERIFY(qtEnum->enumerator_list->value); + QVERIFY(! qtEnum->enumerator_list->next); + + SimpleNameAST *e = qtEnum->enumerator_list->value->asSimpleName(); + QVERIFY(e); + QCOMPARE(unit->spell(e->identifier_token), "e"); +} + QTEST_APPLESS_MAIN(tst_AST) #include "tst_ast.moc" diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 368185424150de55a3f7f78381b668885730ae8d..4b4c22709df42ba443c20d6ecf4ee5c0c7335d40 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -32,12 +32,14 @@ public: TranslationUnit *parse(const QByteArray &source, TranslationUnit::ParseMode mode, - bool enableObjc) + bool enableObjc, + bool qtMocRun) { const StringLiteral *fileId = control.findOrInsertStringLiteral("<stdin>"); TranslationUnit *unit = new TranslationUnit(&control, fileId); unit->setSource(source.constData(), source.length()); unit->setObjCEnabled(enableObjc); + unit->setQtMocRunEnabled(qtMocRun); unit->parse(mode); return unit; } @@ -92,10 +94,10 @@ public: Diagnostic diag; - QSharedPointer<Document> document(const QByteArray &source, bool enableObjc = false) + QSharedPointer<Document> document(const QByteArray &source, bool enableObjc = false, bool qtMocRun = false) { diag.errorCount = 0; // reset the error count. - TranslationUnit *unit = parse(source, TranslationUnit::ParseTranlationUnit, enableObjc); + TranslationUnit *unit = parse(source, TranslationUnit::ParseTranlationUnit, enableObjc, qtMocRun); QSharedPointer<Document> doc(new Document(unit)); doc->check(); doc->errorCount = diag.errorCount; @@ -128,6 +130,8 @@ private slots: void bracketed_expression_under_cursor_8(); void objcClass_1(); + + void q_enum_1(); }; void tst_Semantic::function_declaration_1() @@ -621,5 +625,32 @@ void tst_Semantic::objcClass_1() QVERIFY(!deallocMethod->isStatic()); } +void tst_Semantic::q_enum_1() +{ + QSharedPointer<Document> doc = document("\n" + "class Tst {\n" + "Q_ENUMS(e)\n" + "public:\n" + "enum e { x, y };\n" + "};\n", + false, true); + + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 1U); + QVERIFY(doc->unit); + TranslationUnitAST *xUnit = doc->unit->ast()->asTranslationUnit(); + QVERIFY(xUnit); + SimpleDeclarationAST *tstDecl = xUnit->declaration_list->value->asSimpleDeclaration(); + QVERIFY(tstDecl); + ClassSpecifierAST *tst = tstDecl->decl_specifier_list->value->asClassSpecifier(); + QVERIFY(tst); + QtEnumDeclarationAST *qtEnum = tst->member_specifier_list->value->asQtEnumDeclaration(); + QVERIFY(qtEnum); + SimpleNameAST *e = qtEnum->enumerator_list->value->asSimpleName(); + QVERIFY(e); + QCOMPARE(doc->unit->spell(e->identifier_token), "e"); + QCOMPARE(e->name->identifier()->chars(), "e"); +} + QTEST_APPLESS_MAIN(tst_Semantic) #include "tst_semantic.moc"