diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.cpp b/src/libs/cplusplus/CheckUndefinedSymbols.cpp index 7b1d0a8f79c8ee55dfb403890c0901ddb5b14cfc..245b6be21eaddacd7a2037164f76a56645a8f035 100644 --- a/src/libs/cplusplus/CheckUndefinedSymbols.cpp +++ b/src/libs/cplusplus/CheckUndefinedSymbols.cpp @@ -137,6 +137,12 @@ protected: virtual bool visit(Function *symbol) { + for (TemplateParameters *p = symbol->templateParameters(); p; p = p->previous()) { + Scope *scope = p->scope(); + for (unsigned i = 0; i < scope->symbolCount(); ++i) + accept(scope->symbolAt(i)); + } + addScope(symbol); return true; } @@ -183,6 +189,12 @@ protected: virtual bool visit(Class *symbol) { + for (TemplateParameters *p = symbol->templateParameters(); p; p = p->previous()) { + Scope *scope = p->scope(); + for (unsigned i = 0; i < scope->symbolCount(); ++i) + accept(scope->symbolAt(i)); + } + addScope(symbol); addType(symbol->name()); return true; @@ -190,6 +202,12 @@ protected: virtual bool visit(ForwardClassDeclaration *symbol) { + for (TemplateParameters *p = symbol->templateParameters(); p; p = p->previous()) { + Scope *scope = p->scope(); + for (unsigned i = 0; i < scope->symbolCount(); ++i) + accept(scope->symbolAt(i)); + } + addType(symbol->name()); return true; } @@ -326,16 +344,13 @@ void CheckUndefinedSymbols::checkNamespace(NameAST *name) void CheckUndefinedSymbols::checkName(NameAST *ast) { if (ast->name) { - const QByteArray id = QByteArray::fromRawData(ast->name->identifier()->chars(), // ### move - ast->name->identifier()->size()); - if (_potentialTypes.contains(id)) { - const unsigned tokenOffset = tokenAt(ast->firstToken()).offset; - Scope *scope = CollectTypes::findScope(tokenOffset, _scopes); // ### move - if (! scope) - scope = _context.thisDocument()->globalSymbols(); - - const QList<Symbol *> candidates = _context.lookup(ast->name, scope); - addTypeUsage(candidates, ast); + if (const Identifier *ident = ast->name->identifier()) { + const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size()); + if (_potentialTypes.contains(id)) { + Scope *scope = findScope(ast); + const QList<Symbol *> candidates = _context.lookup(ast->name, scope); + addTypeUsage(candidates, ast); + } } } } @@ -354,34 +369,24 @@ bool CheckUndefinedSymbols::visit(TemplateIdAST *ast) bool CheckUndefinedSymbols::visit(DestructorNameAST *ast) { - if (ast->name) { - const QByteArray id = QByteArray::fromRawData(ast->name->identifier()->chars(), // ### move - ast->name->identifier()->size()); - if (_potentialTypes.contains(id)) { - Scope *scope = CollectTypes::findScope(tokenAt(ast->firstToken()).offset, _scopes); // ### move - if (! scope) - scope = _context.thisDocument()->globalSymbols(); - - ClassOrNamespace *b = _context.lookupType(ast->name, scope); - addTypeUsage(b, ast); - } - } - + checkName(ast); return true; } bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast) { if (ast->name) { - Scope *scope = CollectTypes::findScope(tokenAt(ast->firstToken()).offset, _scopes); // ### move - if (! scope) - scope = _context.thisDocument()->globalSymbols(); + Scope *scope = findScope(ast); ClassOrNamespace *b = 0; if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) { NestedNameSpecifierAST *nested_name_specifier = it->value; NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name; // ### remove shadowing + if (class_or_namespace_name) + if (TemplateIdAST *template_id = class_or_namespace_name->asTemplateId()) + accept(template_id->template_argument_list); + const Name *name = class_or_namespace_name->name; b = _context.lookupType(name, scope); addTypeUsage(b, class_or_namespace_name); @@ -390,6 +395,9 @@ bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast) NestedNameSpecifierAST *nested_name_specifier = it->value; if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) { + if (TemplateIdAST *template_id = class_or_namespace_name->asTemplateId()) + accept(template_id->template_argument_list); + b = b->findType(class_or_namespace_name->name); addTypeUsage(b, class_or_namespace_name); } @@ -403,17 +411,53 @@ bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast) return false; } +bool CheckUndefinedSymbols::visit(TypenameTypeParameterAST *ast) +{ + if (ast->name) { + if (const Identifier *templId = ast->name->name->identifier()) { + const QByteArray id = QByteArray::fromRawData(templId->chars(), templId->size()); + if (_potentialTypes.contains(id)) { + Scope *scope = findScope(_templateDeclarationStack.back()); + const QList<Symbol *> candidates = _context.lookup(ast->name->name, scope); + addTypeUsage(candidates, ast->name); + } + } + } + return true; +} + +bool CheckUndefinedSymbols::visit(TemplateTypeParameterAST *ast) +{ + checkName(ast->name); + return true; +} + +bool CheckUndefinedSymbols::visit(TemplateDeclarationAST *ast) +{ + _templateDeclarationStack.append(ast); + return true; +} + +void CheckUndefinedSymbols::endVisit(TemplateDeclarationAST *) +{ + _templateDeclarationStack.takeFirst(); +} + void CheckUndefinedSymbols::addTypeUsage(ClassOrNamespace *b, NameAST *ast) { if (! b) return; - const Token &tok = tokenAt(ast->firstToken()); + unsigned startToken = ast->firstToken(); + if (DestructorNameAST *dtor = ast->asDestructorName()) + startToken = dtor->identifier_token; + + const Token &tok = tokenAt(startToken); if (tok.generated()) return; unsigned line, column; - getTokenStartPosition(ast->firstToken(), &line, &column); + getTokenStartPosition(startToken, &line, &column); const unsigned length = tok.length(); Use use(line, column, length); _typeUsages.append(use); @@ -422,12 +466,16 @@ void CheckUndefinedSymbols::addTypeUsage(ClassOrNamespace *b, NameAST *ast) void CheckUndefinedSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast) { - const Token &tok = tokenAt(ast->firstToken()); + unsigned startToken = ast->firstToken(); + if (DestructorNameAST *dtor = ast->asDestructorName()) + startToken = dtor->identifier_token; + + const Token &tok = tokenAt(startToken); if (tok.generated()) return; unsigned line, column; - getTokenStartPosition(ast->firstToken(), &line, &column); + getTokenStartPosition(startToken, &line, &column); const unsigned length = tok.length(); foreach (Symbol *c, candidates) { @@ -450,3 +498,34 @@ QList<CheckUndefinedSymbols::Use> CheckUndefinedSymbols::typeUsages() const { return _typeUsages; } + +unsigned CheckUndefinedSymbols::startOfTemplateDeclaration(TemplateDeclarationAST *ast) const +{ + if (ast->declaration) { + if (TemplateDeclarationAST *templ = ast->declaration->asTemplateDeclaration()) + return startOfTemplateDeclaration(templ); + + return ast->declaration->firstToken(); + } + + return ast->firstToken(); +} + +Scope *CheckUndefinedSymbols::findScope(AST *ast) const +{ + Scope *scope = 0; + + if (ast) { + unsigned startToken = ast->firstToken(); + if (TemplateDeclarationAST *templ = ast->asTemplateDeclaration()) + startToken = startOfTemplateDeclaration(templ); + + const unsigned tokenOffset = tokenAt(startToken).offset; + scope = CollectTypes::findScope(tokenOffset, _scopes); + } + + if (! scope) + scope = _context.thisDocument()->globalSymbols(); + + return scope; +} diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.h b/src/libs/cplusplus/CheckUndefinedSymbols.h index 0ca9f5184e1af9cc72442ac7959a255797a94bbf..fd5ffbc78610a1804fe2f77d5869d845f78ef88b 100644 --- a/src/libs/cplusplus/CheckUndefinedSymbols.h +++ b/src/libs/cplusplus/CheckUndefinedSymbols.h @@ -58,6 +58,7 @@ public: protected: using ASTVisitor::visit; + using ASTVisitor::endVisit; bool warning(unsigned line, unsigned column, const QString &text, unsigned length = 0); bool warning(AST *ast, const QString &text); @@ -77,6 +78,15 @@ protected: virtual bool visit(QualifiedNameAST *ast); virtual bool visit(TemplateIdAST *ast); + virtual bool visit(TemplateDeclarationAST *ast); + virtual void endVisit(TemplateDeclarationAST *ast); + + virtual bool visit(TypenameTypeParameterAST *ast); + virtual bool visit(TemplateTypeParameterAST *ast); + + unsigned startOfTemplateDeclaration(TemplateDeclarationAST *ast) const; + Scope *findScope(AST *ast) const; + private: LookupContext _context; QString _fileName; @@ -84,6 +94,7 @@ private: QSet<QByteArray> _potentialTypes; QList<ScopedSymbol *> _scopes; QList<Use> _typeUsages; + QList<TemplateDeclarationAST *> _templateDeclarationStack; }; } // end of namespace CPlusPlus diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp index 795de07f9357fbf9f5f4070b061cb3f7c4ff7ba5..190168f919c63734932616a310d1e63987af8b02 100644 --- a/src/libs/cplusplus/FindUsages.cpp +++ b/src/libs/cplusplus/FindUsages.cpp @@ -28,6 +28,7 @@ **************************************************************************/ #include "FindUsages.h" +#include "Overview.h" #include <Control.h> #include <Literals.h> @@ -436,3 +437,54 @@ bool FindUsages::visit(QtPropertyDeclarationAST *) void FindUsages::endVisit(QtPropertyDeclarationAST *) { _inQProperty = false; } + +bool FindUsages::visit(TemplateDeclarationAST *ast) +{ + _templateDeclarationStack.append(ast); + return true; +} + +void FindUsages::endVisit(TemplateDeclarationAST *) +{ + _templateDeclarationStack.takeFirst(); +} + +bool FindUsages::visit(TypenameTypeParameterAST *ast) +{ + if (NameAST *name = ast->name) { + const Identifier *id = name->name->identifier(); + if (id == _id) { + unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back()); + const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start)); + reportResult(ast->name->firstToken(), candidates); + } + } + accept(ast->type_id); + return false; +} + +bool FindUsages::visit(TemplateTypeParameterAST *ast) +{ + if (NameAST *name = ast->name) { + const Identifier *id = name->name->identifier(); + if (id == _id) { + unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back()); + const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start)); + reportResult(ast->name->firstToken(), candidates); + } + } + accept(ast->type_id); + return false; +} + +unsigned FindUsages::startOfTemplateDeclaration(TemplateDeclarationAST *ast) const +{ + if (ast->declaration) { + if (TemplateDeclarationAST *templ = ast->declaration->asTemplateDeclaration()) + return startOfTemplateDeclaration(templ); + + return ast->declaration->firstToken(); + } + + return ast->firstToken(); +} diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h index 1bcaa66609b5f2319f6597b30d30328f1ca8dcef..d2809db995a259fc9cfd4e726c2aba4b9dcb3963 100644 --- a/src/libs/cplusplus/FindUsages.h +++ b/src/libs/cplusplus/FindUsages.h @@ -99,6 +99,14 @@ protected: virtual bool visit(QtPropertyDeclarationAST *); virtual void endVisit(QtPropertyDeclarationAST *); + virtual bool visit(TemplateDeclarationAST *ast); + virtual void endVisit(TemplateDeclarationAST *ast); + + virtual bool visit(TypenameTypeParameterAST *ast); + virtual bool visit(TemplateTypeParameterAST *ast); + + unsigned startOfTemplateDeclaration(TemplateDeclarationAST *ast) const; + private: const Identifier *_id; Symbol *_declSymbol; @@ -110,6 +118,7 @@ private: Semantic _sem; QList<PostfixExpressionAST *> _postfixExpressionStack; QList<QualifiedNameAST *> _qualifiedNameStack; + QList<TemplateDeclarationAST *> _templateDeclarationStack; QList<int> _references; QList<Usage> _usages; int _inSimpleDeclaration;