diff --git a/src/plugins/cppeditor/cppchecksymbols.cpp b/src/plugins/cppeditor/cppchecksymbols.cpp index 6d8a2e3905dcefd69954162d4e1610cdc5f6fded..add8b3fbe3a82692d9d540678866024878ef14c7 100644 --- a/src/plugins/cppeditor/cppchecksymbols.cpp +++ b/src/plugins/cppeditor/cppchecksymbols.cpp @@ -483,17 +483,8 @@ bool CheckSymbols::visit(NamedTypeSpecifierAST *) bool CheckSymbols::visit(ElaboratedTypeSpecifierAST *ast) { accept(ast->attribute_list); - - if (ast->name) { - if (const Name *name = ast->name->name) { - if (name->isNameId() || name->isTemplateNameId()) { - addUse(ast->name, Use::Type); - return false; - } - } - } - accept(ast->name); + addUse(ast->name, Use::Type); return false; } @@ -678,7 +669,7 @@ bool CheckSymbols::visit(DestructorNameAST *ast) bool CheckSymbols::visit(QualifiedNameAST *ast) { if (ast->name) { - ClassOrNamespace *b = 0; + ClassOrNamespace *binding = 0; if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) { NestedNameSpecifierAST *nested_name_specifier = it->value; if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) { // ### remove shadowing @@ -687,29 +678,39 @@ bool CheckSymbols::visit(QualifiedNameAST *ast) accept(template_id->template_argument_list); const Name *name = class_or_namespace_name->name; - b = _context.lookupType(name, enclosingScope()); - addType(b, class_or_namespace_name); + binding = _context.lookupType(name, enclosingScope()); + addType(binding, class_or_namespace_name); - for (it = it->next; b && it; it = it->next) { + for (it = it->next; it; it = it->next) { 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); + if (TemplateIdAST *template_id = class_or_namespace_name->asTemplateId()) { + if (template_id->template_token) { + addUse(template_id, Use::Type); + binding = 0; // there's no way we can find a binding. + } - b = b->findType(class_or_namespace_name->name); - addType(b, class_or_namespace_name); + accept(template_id->template_argument_list); + if (! binding) + continue; + } + + if (binding) { + binding = binding->findType(class_or_namespace_name->name); + addType(binding, class_or_namespace_name); + } } } } } - if (b && ast->unqualified_name) { + if (binding && ast->unqualified_name) { if (ast->unqualified_name->asDestructorName() != 0) { - if (hasVirtualDestructor(b)) + if (hasVirtualDestructor(binding)) addUse(ast->unqualified_name, Use::VirtualMethod); } else { - addTypeOrStatic(b->find(ast->unqualified_name->name), ast->unqualified_name); + addTypeOrStatic(binding->find(ast->unqualified_name->name), ast->unqualified_name); } } } @@ -805,6 +806,9 @@ void CheckSymbols::addUse(NameAST *ast, Use::Kind kind) if (DestructorNameAST *dtor = ast->asDestructorName()) startToken = dtor->identifier_token; + else if (TemplateIdAST *templ = ast->asTemplateId()) + startToken = templ->identifier_token; + addUse(startToken, kind); } diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 3d5f80a7f53ad675cb6ce55927d0c3da973e00b8..bfe4d2d325cf4c66ae7bf7d28ddfcbf16c90072d 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -3687,6 +3687,8 @@ unsigned TemplateDeclarationAST::lastToken() const /** \generated */ unsigned TemplateIdAST::firstToken() const { + if (template_token) + return template_token; if (identifier_token) return identifier_token; if (less_token) @@ -3711,6 +3713,8 @@ unsigned TemplateIdAST::lastToken() const return less_token + 1; if (identifier_token) return identifier_token + 1; + if (template_token) + return template_token + 1; return 0; } diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index 227eb21483bc43cc7d2cf8bac4ca57052729804a..8db76fb4597118813e362abbe26fdd5de177919f 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -2214,6 +2214,7 @@ protected: class CPLUSPLUS_EXPORT TemplateIdAST: public NameAST { public: + unsigned template_token; unsigned identifier_token; unsigned less_token; ExpressionListAST *template_argument_list; @@ -2221,7 +2222,8 @@ public: public: TemplateIdAST() - : identifier_token(0) + : template_token(0) + , identifier_token(0) , less_token(0) , template_argument_list(0) , greater_token(0) diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index 996d4dbda5b3504f741f9a34ffc53739b5e7d37d..9b837e1384e41e209f4c8a526a50580790a53c2d 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -802,6 +802,7 @@ DestructorNameAST *DestructorNameAST::clone(MemoryPool *pool) const TemplateIdAST *TemplateIdAST::clone(MemoryPool *pool) const { TemplateIdAST *ast = new (pool) TemplateIdAST; + ast->template_token = template_token; ast->identifier_token = identifier_token; ast->less_token = less_token; for (ExpressionListAST *iter = template_argument_list, **ast_iter = &ast->template_argument_list; diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index 2b4c88bf9384d9e7777c53636caa6ca1655f8001..5737bf0f537cf191e9942265c06d67341142e587 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -1347,6 +1347,8 @@ bool ASTMatcher::match(TemplateIdAST *node, TemplateIdAST *pattern) (void) node; (void) pattern; + pattern->template_token = node->template_token; + pattern->identifier_token = node->identifier_token; pattern->less_token = node->less_token; diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 07b0a018a502f0c60caa7950c9ae74e6a1596d06..ad20ef7af4f8c37f7f3a2f83b0628b5ab191b9ee 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -419,14 +419,14 @@ bool Parser::parseClassOrNamespaceName(NameAST *&node) } } else if (LA() == T_TEMPLATE) { unsigned template_token = consumeToken(); - if (parseTemplateId(node)) + if (parseTemplateId(node, template_token)) return true; rewind(template_token); } return false; } -bool Parser::parseTemplateId(NameAST *&node) +bool Parser::parseTemplateId(NameAST *&node, unsigned template_token) { DEBUG_THIS_RULE(); @@ -434,6 +434,7 @@ bool Parser::parseTemplateId(NameAST *&node) if (LA() == T_IDENTIFIER && LA(2) == T_LESS) { TemplateIdAST *ast = new (_pool) TemplateIdAST; + ast->template_token = template_token; ast->identifier_token = consumeToken(); ast->less_token = consumeToken(); if (LA() == T_GREATER || parseTemplateArgumentList( @@ -2642,7 +2643,7 @@ bool Parser::parseUnqualifiedName(NameAST *&node, bool acceptTemplateId) return true; } else if (LA() == T_TEMPLATE) { unsigned template_token = consumeToken(); - if (parseTemplateId(node)) + if (parseTemplateId(node, template_token)) return true; rewind(template_token); } diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index 4b19f1cf10f4629e6db9dd6ab04a457412e6de02..11743346a4e9ebbcc2645476a82140ce2cbcf270 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -147,7 +147,7 @@ public: bool parseMemInitializerList(MemInitializerListAST *&node); bool parseMemberSpecification(DeclarationAST *&node); bool parseMultiplicativeExpression(ExpressionAST *&node); - bool parseTemplateId(NameAST *&node); + bool parseTemplateId(NameAST *&node, unsigned template_token = 0); bool parseClassOrNamespaceName(NameAST *&node); bool parseNameId(NameAST *&node); bool parseName(NameAST *&node, bool acceptTemplateId = true); diff --git a/tests/manual/cplusplus-dump/dumpers.inc b/tests/manual/cplusplus-dump/dumpers.inc index 1ac8ef9eb35f3d1c0eb0b25ba5d0be57f6e7939d..4d090004ad9e04d19642978409c665ee1c66b5e4 100644 --- a/tests/manual/cplusplus-dump/dumpers.inc +++ b/tests/manual/cplusplus-dump/dumpers.inc @@ -771,11 +771,13 @@ virtual bool visit(DestructorNameAST *ast) virtual bool visit(TemplateIdAST *ast) { + if (ast->template_token) + terminal(ast->template_token, ast); if (ast->identifier_token) terminal(ast->identifier_token, ast); if (ast->less_token) terminal(ast->less_token, ast); - for (TemplateArgumentListAST *iter = ast->template_argument_list; iter; iter = iter->next) + for (ExpressionListAST *iter = ast->template_argument_list; iter; iter = iter->next) nonterminal(iter->value); if (ast->greater_token) terminal(ast->greater_token, ast);