diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.cpp b/src/libs/cplusplus/CheckUndefinedSymbols.cpp index bf2c201bb6b1d0be9675fa20b3174b4876ab12f9..d0d69187468ee1f1a4372a6b9f279400db71a682 100644 --- a/src/libs/cplusplus/CheckUndefinedSymbols.cpp +++ b/src/libs/cplusplus/CheckUndefinedSymbols.cpp @@ -61,6 +61,48 @@ void CheckUndefinedSymbols::setGlobalNamespaceBinding(NamespaceBindingPtr global void CheckUndefinedSymbols::operator()(AST *ast) { accept(ast); } +QByteArray CheckUndefinedSymbols::templateParameterName(NameAST *ast) const +{ + if (ast && ast->name) { + if (Identifier *id = ast->name->identifier()) + return QByteArray::fromRawData(id->chars(), id->size()); + } + + return QByteArray(); +} + +QByteArray CheckUndefinedSymbols::templateParameterName(DeclarationAST *ast) const +{ + if (ast) { + if (TypenameTypeParameterAST *d = ast->asTypenameTypeParameter()) + return templateParameterName(d->name); + else if (TemplateTypeParameterAST *d = ast->asTemplateTypeParameter()) + return templateParameterName(d->name); + } + return QByteArray(); +} + +bool CheckUndefinedSymbols::isType(const QByteArray &name) const +{ + for (int i = _templateDeclarationStack.size() - 1; i != - 1; --i) { + TemplateDeclarationAST *templateDeclaration = _templateDeclarationStack.at(i); + for (DeclarationListAST *it = templateDeclaration->template_parameters; it; it = it->next) { + DeclarationAST *templateParameter = it->declaration; + if (templateParameterName(templateParameter) == name) + return true; + } + } + return _types.contains(name); +} + +bool CheckUndefinedSymbols::isType(Identifier *id) const +{ + if (! id) + return false; + + return isType(QByteArray::fromRawData(id->chars(), id->size())); +} + void CheckUndefinedSymbols::addType(Name *name) { if (! name) @@ -124,22 +166,22 @@ void CheckUndefinedSymbols::buildTypeMap(NamespaceBinding *binding, QSet<Namespa FunctionDeclaratorAST *CheckUndefinedSymbols::currentFunctionDeclarator() const { - if (functionDeclarationStack.isEmpty()) + if (_functionDeclaratorStack.isEmpty()) return 0; - return functionDeclarationStack.last(); + return _functionDeclaratorStack.last(); } bool CheckUndefinedSymbols::visit(FunctionDeclaratorAST *ast) { - functionDeclarationStack.append(ast); + _functionDeclaratorStack.append(ast); return true; } void CheckUndefinedSymbols::endVisit(FunctionDeclaratorAST *) { - functionDeclarationStack.removeLast(); + _functionDeclaratorStack.removeLast(); } bool CheckUndefinedSymbols::visit(TypeofSpecifierAST *ast) @@ -148,22 +190,6 @@ bool CheckUndefinedSymbols::visit(TypeofSpecifierAST *ast) return false; } -bool CheckUndefinedSymbols::visit(TypenameTypeParameterAST *ast) -{ - if (NameAST *nameAst = ast->name) - addType(nameAst->name); - - return true; -} - -bool CheckUndefinedSymbols::visit(TemplateTypeParameterAST *ast) -{ - if (ast->name) - addType(ast->name->name); - - return true; -} - bool CheckUndefinedSymbols::visit(NamedTypeSpecifierAST *ast) { if (ast->name) { @@ -172,7 +198,7 @@ bool CheckUndefinedSymbols::visit(NamedTypeSpecifierAST *ast) getTokenStartPosition(ast->firstToken(), &line, &col); // qWarning() << _doc->fileName() << line << col; } else if (Identifier *id = ast->name->name->identifier()) { - if (! _types.contains(QByteArray::fromRawData(id->chars(), id->size()))) { + if (! isType(id)) { if (FunctionDeclaratorAST *functionDeclarator = currentFunctionDeclarator()) { if (functionDeclarator->as_cpp_initializer) return true; @@ -187,6 +213,17 @@ bool CheckUndefinedSymbols::visit(NamedTypeSpecifierAST *ast) return true; } +bool CheckUndefinedSymbols::visit(TemplateDeclarationAST *ast) +{ + _templateDeclarationStack.append(ast); + return true; +} + +void CheckUndefinedSymbols::endVisit(TemplateDeclarationAST *) +{ + _templateDeclarationStack.removeLast(); +} + bool CheckUndefinedSymbols::visit(ClassSpecifierAST *ast) { if (ast->base_clause) { @@ -241,6 +278,9 @@ bool CheckUndefinedSymbols::visit(FunctionDefinitionAST *ast) return true; } +void CheckUndefinedSymbols::endVisit(FunctionDefinitionAST *) +{ } + bool CheckUndefinedSymbols::visit(SimpleDeclarationAST *ast) { const bool check = qobjectCheck(); @@ -265,7 +305,7 @@ bool CheckUndefinedSymbols::visit(BaseSpecifierAST *base) if (Name *name = nameAST->name) { Identifier *id = name->identifier(); const QByteArray spell = QByteArray::fromRawData(id->chars(), id->size()); - if (_types.contains(spell)) + if (isType(spell)) resolvedBaseClassName = true; } @@ -310,7 +350,7 @@ bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast) Name *name = q->nameAt(i); if (Identifier *id = name->identifier()) { const QByteArray spell = QByteArray::fromRawData(id->chars(), id->size()); - if (! (_namespaceNames.contains(spell) || _types.contains(spell))) { + if (! (_namespaceNames.contains(spell) || isType(id))) { translationUnit()->warning(ast->firstToken(), "`%s' is not a namespace or class name", spell.constData()); diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.h b/src/libs/cplusplus/CheckUndefinedSymbols.h index 79e64a1262dcca371a61d1dd13d780b243852c86..8def4931435aa0aa0e1690fa013efb11d423cdaf 100644 --- a/src/libs/cplusplus/CheckUndefinedSymbols.h +++ b/src/libs/cplusplus/CheckUndefinedSymbols.h @@ -52,24 +52,33 @@ public: protected: using ASTVisitor::visit; + bool isType(Identifier *id) const; + bool isType(const QByteArray &name) const; + void addType(Name *name); void buildTypeMap(Class *klass); void buildTypeMap(NamespaceBinding *binding, QSet<NamespaceBinding *> *processed); FunctionDeclaratorAST *currentFunctionDeclarator() const; bool qobjectCheck() const; + QByteArray templateParameterName(NameAST *ast) const; + QByteArray templateParameterName(DeclarationAST *ast) const; + virtual bool visit(FunctionDeclaratorAST *ast); virtual void endVisit(FunctionDeclaratorAST *ast); virtual bool visit(TypeofSpecifierAST *ast); - virtual bool visit(TypenameTypeParameterAST *ast); - virtual bool visit(TemplateTypeParameterAST *ast); virtual bool visit(NamedTypeSpecifierAST *ast); + virtual bool visit(TemplateDeclarationAST *ast); + virtual void endVisit(TemplateDeclarationAST *); + virtual bool visit(ClassSpecifierAST *ast); virtual void endVisit(ClassSpecifierAST *); virtual bool visit(FunctionDefinitionAST *ast); + virtual void endVisit(FunctionDefinitionAST *ast); + virtual bool visit(SimpleDeclarationAST *ast); virtual bool visit(BaseSpecifierAST *base); virtual bool visit(UsingDirectiveAST *ast); @@ -81,7 +90,8 @@ private: Document::Ptr _doc; NamespaceBindingPtr _globalNamespaceBinding; QList<bool> _qobjectStack; - QList<FunctionDeclaratorAST *> functionDeclarationStack; + QList<FunctionDeclaratorAST *> _functionDeclaratorStack; + QList<TemplateDeclarationAST *> _templateDeclarationStack; QSet<QByteArray> _types; QSet<QByteArray> _namespaceNames; };