diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 6f9cf90a852..69c937cfb30 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5725,8 +5725,6 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) simplifyFunctionTryCatch(); - simplifyHeadersAndUnusedTemplates(); - // Remove __asm.. simplifyAsm(); @@ -5754,6 +5752,8 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) // remove __attribute__((?)) simplifyAttribute(); + simplifyHeadersAndUnusedTemplates(); + validate(); // Bail out if code is garbage @@ -6518,7 +6518,7 @@ void Tokenizer::simplifyHeadersAndUnusedTemplates() } } - if (!tok->previous() || Token::Match(tok->previous(), "[;{}]")) { + if (!tok->previous() || Token::Match(tok->previous(), "[;{}:]")) { // Remove unused function declarations if (isIncluded && removeUnusedIncludedFunctions) { while (true) { @@ -6551,7 +6551,7 @@ void Tokenizer::simplifyHeadersAndUnusedTemplates() if (removeUnusedTemplates || (isIncluded && removeUnusedIncludedTemplates)) { if (Token::Match(tok, "template < %name%")) { - const Token *closingBracket = tok->next()->findClosingBracket(); + Token *closingBracket = tok->next()->findClosingBracket(); if (Token::Match(closingBracket, "> class|struct %name% [;:{]") && keep.find(closingBracket->strAt(2)) == keep.end()) { const Token *endToken = closingBracket->tokAt(3); if (endToken->str() == ":") { @@ -6565,11 +6565,58 @@ void Tokenizer::simplifyHeadersAndUnusedTemplates() Token::eraseTokens(tok, endToken); tok->deleteThis(); } - } else if (Token::Match(closingBracket, "> %type% %name% (") && Token::simpleMatch(closingBracket->linkAt(3), ") {") && keep.find(closingBracket->strAt(2)) == keep.end()) { - const Token *endToken = closingBracket->linkAt(3)->linkAt(1)->next(); - Token::eraseTokens(tok, endToken); - tok->deleteThis(); - goBack = true; + } else { + Token *funcTok = closingBracket->next(); + while (funcTok) { + if (Token::Match(funcTok, "::|constexpr|static|inline|const|%type%|&|&&|*") && !Token::Match(funcTok, "%name% (")) { + funcTok = funcTok->next(); + continue; + } + if (Token::simpleMatch(funcTok, "<")) { + funcTok = funcTok->findClosingBracket(); + if (funcTok) { + funcTok = funcTok->next(); + } else { + break; + } + continue; + } + break; + } + if (!funcTok) + break; + if (!Token::Match(funcTok, "%name% (")) { + tok = funcTok; + continue; + } + funcTok = funcTok->linkAt(1); + if (funcTok) { + funcTok = funcTok->next(); + } + while (funcTok) { + if (Token::Match(funcTok, "throw|noexcept (")) { + funcTok = funcTok->linkAt(1); + if (funcTok) { + funcTok = funcTok->next(); + } + continue; + } + if (Token::Match(funcTok, "const|volatile|&|&&")) { + funcTok = funcTok->next(); + continue; + } + break; + } + if (!Token::simpleMatch(funcTok, "{")) { + tok = funcTok; + continue; + } + funcTok = funcTok->link(); + if (funcTok) { + Token::eraseTokens(tok, funcTok->next()); + tok->deleteThis(); + goBack = true; + } } } } diff --git a/test/cli/other_test.py b/test/cli/other_test.py index 243f600b5a6..7a848b04960 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -3415,6 +3415,76 @@ def test_check_unused_templates_func(tmp_path): # #13714 (void)(*((int*)0)); } +class S { +public: + template + void f_t_3() + { + (void)(*((int*)0)); + } +} + +template +static inline void f_t_4() +{ + (void)(*((int*)0)); +} + +template +const void *f_t_5() +{ + (void)(*((int*)0)); +} + +template +void f_t_6() __attribute__((noreturn)) +{ + (void)(*((int*)0)); +} + +template +__attribute__((noreturn)) void f_t_7() +{ + (void)(*((int*)0)); +} + +template +__declspec(noreturn) void f_t_8() +{ + (void)(*((int*)0)); +} + +template +[[noreturn]] void f_t_9() +{ + (void)(*((int*)0)); +} + +template +void f_t_10() noexcept(true) +{ + (void)(*((int*)0)); +} + +template +void f_t_11() throw(true) +{ + (void)(*((int*)0)); +} + +struct S { + template + void f_t_12() const { + (void)(*((int*)0)); + } +}; + +template +std::vector f_t_13() { + (void)(*((int*)0)); + return {}; +} + void f() {} """)