diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 113d68e8b66..ff94286cb20 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -127,7 +127,7 @@ const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &end if (Token::Match(tok, "%name% (") && tok->isUpperCaseName()) tok = tok->linkAt(1)->next(); if (tok && tok->originalName() == "->") { // trailing return type - for (tok = tok->next(); tok && !Token::Match(tok, ";|{|override|final"); tok = tok->next()) + for (tok = tok->next(); tok && !Token::Match(tok, ";|{|override|final|}|)|]"); tok = tok->next()) if (tok->link() && Token::Match(tok, "<|[|(")) tok = tok->link(); } @@ -136,6 +136,14 @@ const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &end tok = tok->next(); if (Token::Match(tok, "= 0|default|delete ;")) tok = tok->tokAt(2); + if (Token::simpleMatch(tok, "requires")) { + for (tok = tok->next(); tok && !Token::Match(tok, ";|{|}|)|]"); tok = tok->next()) { + if (tok->link() && Token::Match(tok, "<|[|(")) + tok = tok->link(); + if (Token::simpleMatch(tok, "bool {")) + tok = tok->linkAt(1); + } + } if (tok && tok->str() == ":" && !Token::Match(tok->next(), "%name%|::")) return nullptr; return (tok && endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 5dacd24e065..b390bde021a 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -7605,6 +7605,12 @@ class TestTokenizer : public TestFixture { { ASSERT_NO_THROW(tokenizeAndStringify("template\n" "struct X { X(U) requires true {} };\n")); + ASSERT_NO_THROW(tokenizeAndStringify("template\n" + "struct X { X(U) requires bool{std::is_integral{}} {} };\n")); + ASSERT_NO_THROW(tokenizeAndStringify("template \n" + "struct test { operator int() requires true { return 0; } };\n")); + ASSERT_NO_THROW(tokenizeAndStringify("template \n" + "struct test { operator int() requires bool{std::is_integral{}} { return 0; } };\n")); } void noCrash1() {