From efb600665d3cb277d330974bcfd90a1da8dc6395 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Thu, 12 Aug 2010 12:18:49 +0200 Subject: [PATCH] Remember the T_TEMPLATE token we use to force the parser to recognize a template-id. --- src/plugins/cppeditor/cppchecksymbols.cpp | 46 ++++++++++++----------- src/shared/cplusplus/AST.cpp | 4 ++ src/shared/cplusplus/AST.h | 4 +- src/shared/cplusplus/ASTClone.cpp | 1 + src/shared/cplusplus/ASTMatcher.cpp | 2 + src/shared/cplusplus/Parser.cpp | 7 ++-- src/shared/cplusplus/Parser.h | 2 +- tests/manual/cplusplus-dump/dumpers.inc | 4 +- 8 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/plugins/cppeditor/cppchecksymbols.cpp b/src/plugins/cppeditor/cppchecksymbols.cpp index 6d8a2e3905d..add8b3fbe3a 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 3d5f80a7f53..bfe4d2d325c 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 227eb21483b..8db76fb4597 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 996d4dbda5b..9b837e1384e 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 2b4c88bf938..5737bf0f537 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 07b0a018a50..ad20ef7af4f 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 4b19f1cf10f..11743346a4e 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 1ac8ef9eb35..4d090004ad9 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); -- GitLab