Detect lambda with template argument (#5202)
This commit is contained in:
parent
0a72cd3b72
commit
4f71bbe986
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue