Detect lambda with template argument (#5202)

This commit is contained in:
chrchr-github 2023-06-27 16:19:12 +02:00 committed by GitHub
parent 0a72cd3b72
commit 4f71bbe986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 5 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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 = []<typename T>() {\n"
" return true;\n"
" };\n"
" return nullptr;\n"
"}\n");
ASSERT(db && db->scopeList.size() == 3);
std::list<Scope>::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<template<class> class E,class D> class C : E<D> {\n"