diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 0aebf0d02..bf612cf04 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -699,18 +699,24 @@ bool TemplateSimplifier::instantiateMatch(const Token *instance, const std::stri int TemplateSimplifier::getTemplateNamePosition(const Token *tok) { // get the position of the template name - int namepos = 0; + int namepos = 0, starAmpPossiblePosition = 0; if (Token::Match(tok, "> class|struct %type% {|:")) namepos = 2; else if (Token::Match(tok, "> %type% *|&| %type% (")) namepos = 2; else if (Token::Match(tok, "> %type% %type% *|&| %type% (")) namepos = 3; - else { + else if (Token::Match(tok, "> %type% *|&| %type% :: %type% (")) { + namepos = 4; + starAmpPossiblePosition = 2; + } else if (Token::Match(tok, "> %type% %type% *|&| %type% :: %type% (")) { + namepos = 5; + starAmpPossiblePosition = 3; + } else { // Name not found return -1; } - if ((tok->strAt(namepos) == "*" || tok->strAt(namepos) == "&")) + if (Token::Match(tok->tokAt(starAmpPossiblePosition ? starAmpPossiblePosition : namepos), "*|&")) ++namepos; return namepos; diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index ef9e0a59d..6f5d29b6c 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -95,6 +95,8 @@ private: // Test TemplateSimplifier::templateParameters TEST_CASE(templateParameters); TEST_CASE(templateParameters1); // #4169 - segmentation fault + + TEST_CASE(templateNamePosition); } std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Unspecified) { @@ -1110,6 +1112,43 @@ private: // do not crash on invalid code ASSERT_EQUALS(0, templateParameters(code)); } + + // Helper function to unit test TemplateSimplifier::getTemplateNamePosition + int templateNamePositionHelper(const char code[], unsigned offset = 0) { + Settings settings; + Tokenizer tokenizer(&settings, this); + + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp", "", true); + + const Token *tok = tokenizer.tokens(); + for (unsigned i = 0 ; i < offset ; ++i) + tok = tok->next(); + return TemplateSimplifier::getTemplateNamePosition(tok); + } + + void templateNamePosition() { + // Template class + ASSERT_EQUALS(2, templateNamePositionHelper("template class A {};", 4)); + ASSERT_EQUALS(2, templateNamePositionHelper("template struct A {};", 4)); + ASSERT_EQUALS(2, templateNamePositionHelper("template class A : B {};", 4)); + ASSERT_EQUALS(2, templateNamePositionHelper("template struct A : B {};", 4)); + // Template function definitions + ASSERT_EQUALS(2, templateNamePositionHelper("template unsigned foo() { return 0; }", 4)); + ASSERT_EQUALS(3, templateNamePositionHelper("template unsigned* foo() { return 0; }", 4)); + ASSERT_EQUALS(3, templateNamePositionHelper("template const unsigned foo() { return 0; }", 4)); + ASSERT_EQUALS(4, templateNamePositionHelper("template const unsigned& foo() { return 0; }", 4)); + // Class template members + ASSERT_EQUALS(4, templateNamePositionHelper("class A { template unsigned foo(); }; " + "template unsigned A::foo() { return 0; }", 19)); + ASSERT_EQUALS(5, templateNamePositionHelper("class A { template const unsigned foo(); }; " + "template const unsigned A::foo() { return 0; }", 20)); + TODO_ASSERT_EQUALS(7, -1, templateNamePositionHelper("class A { class B { template const unsigned foo(); }; } ; " + "template const unsigned A::B::foo() { return 0; }", 25)); + // Template class member + TODO_ASSERT_EQUALS(7, -1, templateNamePositionHelper("template class A { unsigned foo(); }; " + "template unsigned A::foo() { return 0; }", 19)); + } }; REGISTER_TEST(TestSimplifyTemplate)