diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 20d36c54c..c3d70d0cf 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2977,9 +2977,12 @@ T* findLambdaEndTokenGeneric(T* first) return nullptr; if (!maybeLambda(first->previous())) return nullptr; - if (!Token::Match(first->link(), "] (|{")) + if (!Token::Match(first->link(), "] (|{|<")) return nullptr; - if (first->astOperand1() != first->link()->next()) + const Token* roundOrCurly = first->link()->next(); + if (roundOrCurly->link() && roundOrCurly->str() == "<") + roundOrCurly = roundOrCurly->link()->next(); + if (first->astOperand1() != roundOrCurly) return nullptr; T * tok = first; diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index c4e7f0304..b4af023ba 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -909,7 +909,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state) } compileBinOp(tok, state, compileScope); } else if (tok->str() == "[") { - if (state.cpp && isPrefixUnary(tok, state.cpp) && Token::Match(tok->link(), "] (|{")) { // Lambda + if (state.cpp && isPrefixUnary(tok, state.cpp) && Token::Match(tok->link(), "] (|{|<")) { // Lambda // What we do here: // - Nest the round bracket under the square bracket. // - Nest what follows the lambda (if anything) with the lambda opening [ @@ -926,8 +926,10 @@ static void compilePrecedence2(Token *&tok, AST_state& state) } } - if (Token::simpleMatch(squareBracket->link(), "] (")) { - Token* const roundBracket = squareBracket->link()->next(); + const bool hasTemplateArg = Token::simpleMatch(squareBracket->link(), "] <") && + Token::simpleMatch(squareBracket->link()->next()->link(), "> ("); + if (Token::simpleMatch(squareBracket->link(), "] (") || hasTemplateArg) { + Token* const roundBracket = hasTemplateArg ? squareBracket->link()->next()->link()->next() : squareBracket->link()->next(); Token* curlyBracket = roundBracket->link()->next(); while (Token::Match(curlyBracket, "mutable|const|constexpr|consteval")) curlyBracket = curlyBracket->next(); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index a9d0af457..149f5b3e3 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -472,6 +472,7 @@ private: TEST_CASE(lambda2); // #7473 TEST_CASE(lambda3); TEST_CASE(lambda4); + TEST_CASE(lambda5); TEST_CASE(circularDependencies); // #6298 @@ -7775,6 +7776,26 @@ private: ASSERT_EQUALS(s.type()->classScope, &*scope); } + void lambda5() { // #11275 + GET_SYMBOL_DB("int* f() {\n" + " auto g = []() {\n" + " return true;\n" + " };\n" + " return nullptr;\n" + "}\n"); + + ASSERT(db && db->scopeList.size() == 3); + std::list::const_iterator scope = db->scopeList.cbegin(); + ASSERT_EQUALS(Scope::eGlobal, scope->type); + ++scope; + ASSERT_EQUALS(Scope::eFunction, scope->type); + ++scope; + ASSERT_EQUALS(Scope::eLambda, scope->type); + const Token* ret = Token::findsimplematch(tokenizer.tokens(), "return true"); + ASSERT(ret && ret->scope()); + ASSERT_EQUALS(ret->scope()->type, Scope::eLambda); + } + // #6298 "stack overflow in Scope::findFunctionInBase (endless recursion)" void circularDependencies() { check("template class E,class D> class C : E {\n"