diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 541888957..e37c49fc6 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3847,7 +3847,9 @@ void Tokenizer::createLinks2() while (!type.empty() && type.top()->str() == "<") type.pop(); - } else if (token->str() == "<" && token->previous() && token->previous()->isName() && !token->previous()->varId()) { + } else if (token->str() == "<" && + ((token->previous() && token->previous()->isName() && !token->previous()->varId()) || + Token::Match(token->next(), ">|>>"))) { type.push(token); if (!templateToken && (token->previous()->str() == "template")) templateToken = token; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 668c41730..db70c90cc 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -455,6 +455,7 @@ private: // The TestGarbage ensures that there are true positives TEST_CASE(findGarbageCode); TEST_CASE(checkEnableIf); + TEST_CASE(checkTemplates); // #9052 TEST_CASE(noCrash1); @@ -4795,6 +4796,18 @@ private: tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "<")->link()); } + + { + // #8890 + const char code[] = "void f() {\n" + " a<> b;\n" + " b.a<>::c();\n" + "}\n"; + Tokenizer tokenizer(&settings0, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> ::")->link()); + } } void simplifyString() { @@ -7583,6 +7596,18 @@ private: } + void checkTemplates() { + ASSERT_NO_THROW(tokenizeAndStringify( + "template struct a {\n" + " void c();\n" + "};\n" + "void f() {\n" + " a<> b;\n" + " b.a<>::c();\n" + "}\n")) + } + + void noCrash1() { ASSERT_NO_THROW(tokenizeAndStringify( "struct A {\n"