diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5dcd16aaa..00178cca7 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3792,6 +3792,7 @@ void Tokenizer::createLinks2() const Token * templateToken = nullptr; bool isStruct = false; + std::set usingNames; std::map templateNames; templateNames["template"] = true; @@ -3802,6 +3803,14 @@ void Tokenizer::createLinks2() else if (Token::Match(token, "[;{}]")) isStruct = false; + if (Token::Match(token, "using %name% ::")) { + const Token *tok2 = token->tokAt(3); + while (Token::Match(tok2, "%name% ::")) + tok2 = tok2->tokAt(2); + if (Token::Match(tok2, "%name% ;")) + usingNames.insert(tok2->str()); + } + if (token->link()) { if (Token::Match(token, "{|[|(")) type.push(token); @@ -3851,7 +3860,11 @@ void Tokenizer::createLinks2() while (!type.empty() && type.top()->str() == "<") type.pop(); } else if (token->str() == "<" && token->previous() && token->previous()->isName() && !token->previous()->varId()) { - if (!Token::simpleMatch(token->tokAt(-2), "::")) { + const bool isScoped = Token::simpleMatch(token->tokAt(-2), "::") || + (Token::Match(token->tokAt(-2), "; %name% <") && usingNames.count(token->previous()->str())); + const bool isTemplateDecl = isScoped || Token::Match(token->tokAt(-2), "%name% %name% <"); + const bool isTemplateArgPointerType = Token::Match(token, "< %name%| %stype% * >"); + if (!isTemplateDecl && !isTemplateArgPointerType) { std::map::const_iterator it = templateNames.find(token->previous()->str()); if (it == templateNames.end()) { const std::string &name = token->previous()->str(); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 000af6024..11f6b3a40 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -4771,13 +4771,22 @@ private: } { - // #9094 + // #9094 - template usage or comparison? const char code[] = "a = f(x%x<--a==x>x);"; Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr == Token::findsimplematch(tokenizer.tokens(), "<")->link()); } + + { + // #9131 - template usage or comparison? + const char code[] = "using std::list; list l;"; + Tokenizer tokenizer(&settings0, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "<")->link()); + } } void simplifyString() { @@ -7337,7 +7346,7 @@ private: const char code1[] = "using uno::Ref;\n" "Ref r;\n" "int x(0);"; - ASSERT_EQUALS("unoRef:: RefX x0(", testAst(code1)); + ASSERT_EQUALS("unoRef:: x0(", testAst(code1)); } void astunaryop() { // unary operators