diff --git a/lib/token.h b/lib/token.h index daa176d02..48bcfc916 100644 --- a/lib/token.h +++ b/lib/token.h @@ -641,6 +641,13 @@ public: setFlag(fIsInline, b); } + bool isTemplate() const { + return getFlag(fIsTemplate); + } + void isTemplate(bool b) { + setFlag(fIsTemplate, b); + } + bool isBitfield() const { return mImpl->mBits > 0; } @@ -1239,7 +1246,8 @@ private: fIsSplitVarDeclComma = (1 << 29), // set to true when variable declarations are split up ('int a,b;' => 'int a; int b;') fIsSplitVarDeclEq = (1 << 30), // set to true when variable declaration with initialization is split up ('int a=5;' => 'int a; a=5;') fIsImplicitInt = (1U << 31), // Is "int" token implicitly added? - fIsInline = (1ULL << 32) // Is this a inline type + fIsInline = (1ULL << 32), // Is this a inline type + fIsTemplate = (1ULL << 33) }; Token::Type mTokType; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5dc6a4d8d..aa712a588 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4509,7 +4509,8 @@ void Tokenizer::createLinks2() type.pop(); } } else if (token->str() == "<" && - ((token->previous() && token->previous()->isName() && !token->previous()->varId()) || + ((token->previous() && (token->previous()->isTemplate() || + (token->previous()->isName() && !token->previous()->varId()))) || Token::Match(token->next(), ">|>>"))) { type.push(token); if (!templateToken && (token->previous()->str() == "template")) @@ -5634,8 +5635,19 @@ void Tokenizer::removeExtraTemplateKeywords() { if (isCPP()) { for (Token *tok = list.front(); tok; tok = tok->next()) { - if (Token::Match(tok, "%name%|> .|:: template %name%")) + if (Token::Match(tok, "%name%|>|) .|:: template %name%")) { tok->next()->deleteNext(); + Token* templateName = tok->tokAt(2); + while (Token::Match(templateName, "%name%|::")) { + templateName->isTemplate(true); + templateName = templateName->next(); + } + if (Token::Match(templateName->previous(), "operator %op%|(")) { + templateName->isTemplate(true); + if (templateName->str() == "(" && templateName->link()) + templateName->link()->isTemplate(true); + } + } } } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 224780225..5c6392797 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -6632,6 +6632,12 @@ private: " for (size_t e = 0; e < d; e++)\n" " ;\n" "}\n")); + + ASSERT_NO_THROW(tokenizeAndStringify( + "template \n" + "constexpr void constexpr_for_fold_impl([[maybe_unused]] Functor&& f, std::index_sequence) noexcept {\n" + " (std::forward(f).template operator() < First + Indices > (), ...);\n" + "}\n")); } void checkNamespaces() {