AST: Fix AST for lambda '[&]{..}'
This commit is contained in:
parent
59b0c6f6b1
commit
e6005dfa3c
|
@ -677,34 +677,40 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
|
||||||
} else
|
} else
|
||||||
compileBinOp(tok, state, compileScope);
|
compileBinOp(tok, state, compileScope);
|
||||||
} else if (tok->str() == "[") {
|
} else if (tok->str() == "[") {
|
||||||
bool lambda = false;
|
if (state.cpp && isPrefixUnary(tok, state.cpp) && Token::Match(tok->link(), " ] (|{")) { // Lambda
|
||||||
if (state.cpp && isPrefixUnary(tok, state.cpp) && tok->link()->strAt(1) == "(") { // Lambda
|
|
||||||
// What we do here:
|
// What we do here:
|
||||||
// - Nest the round bracket under the square bracket.
|
// - Nest the round bracket under the square bracket.
|
||||||
// - Nest what follows the lambda (if anything) with the lambda opening [
|
// - Nest what follows the lambda (if anything) with the lambda opening [
|
||||||
// - Compile the content of the lambda function as separate tree (this is done later)
|
// - Compile the content of the lambda function as separate tree (this is done later)
|
||||||
// this must be consistent with isLambdaCaptureList
|
// this must be consistent with isLambdaCaptureList
|
||||||
Token* squareBracket = tok;
|
Token* const squareBracket = tok;
|
||||||
Token* roundBracket = squareBracket->link()->next();
|
if (Token::simpleMatch(squareBracket->link(), "] (")) {
|
||||||
|
Token* const roundBracket = squareBracket->link()->next();
|
||||||
Token* curlyBracket = roundBracket->link()->next();
|
Token* curlyBracket = roundBracket->link()->next();
|
||||||
while (Token::Match(curlyBracket, "%name%|.|::"))
|
while (Token::Match(curlyBracket, "%name%|.|::"))
|
||||||
curlyBracket = curlyBracket->next();
|
curlyBracket = curlyBracket->next();
|
||||||
if (Token::simpleMatch(curlyBracket, "{")) {
|
if (curlyBracket && curlyBracket->str() == "{") {
|
||||||
lambda = true;
|
|
||||||
squareBracket->astOperand1(roundBracket);
|
squareBracket->astOperand1(roundBracket);
|
||||||
roundBracket->astOperand1(curlyBracket);
|
roundBracket->astOperand1(curlyBracket);
|
||||||
state.op.push(squareBracket);
|
state.op.push(squareBracket);
|
||||||
tok = curlyBracket->link()->next();
|
tok = curlyBracket->link()->next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Token* const curlyBracket = squareBracket->link()->next();
|
||||||
|
squareBracket->astOperand1(curlyBracket);
|
||||||
|
state.op.push(squareBracket);
|
||||||
|
tok = curlyBracket->link()->next();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!lambda) {
|
|
||||||
Token* tok2 = tok;
|
Token* tok2 = tok;
|
||||||
if (tok->strAt(1) != "]")
|
if (tok->strAt(1) != "]")
|
||||||
compileBinOp(tok, state, compileExpression);
|
compileBinOp(tok, state, compileExpression);
|
||||||
else
|
else
|
||||||
compileUnaryOp(tok, state, compileExpression);
|
compileUnaryOp(tok, state, compileExpression);
|
||||||
tok = tok2->link()->next();
|
tok = tok2->link()->next();
|
||||||
}
|
|
||||||
} else if (tok->str() == "(" && (!iscast(tok) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
|
} else if (tok->str() == "(" && (!iscast(tok) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
|
||||||
Token* tok2 = tok;
|
Token* tok2 = tok;
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
@ -986,11 +992,13 @@ static bool isLambdaCaptureList(const Token * tok)
|
||||||
{
|
{
|
||||||
// a lambda expression '[x](y){}' is compiled as:
|
// a lambda expression '[x](y){}' is compiled as:
|
||||||
// [
|
// [
|
||||||
// `-(
|
// `-( <<-- optional
|
||||||
// `-{
|
// `-{
|
||||||
// see compilePrecedence2
|
// see compilePrecedence2
|
||||||
if (tok->str() != "[")
|
if (tok->str() != "[")
|
||||||
return false;
|
return false;
|
||||||
|
if (Token::simpleMatch(tok->astOperand1(), "{"))
|
||||||
|
return true;
|
||||||
if (!tok->astOperand1() || tok->astOperand1()->str() != "(")
|
if (!tok->astOperand1() || tok->astOperand1()->str() != "(")
|
||||||
return false;
|
return false;
|
||||||
const Token * params = tok->astOperand1();
|
const Token * params = tok->astOperand1();
|
||||||
|
@ -1035,6 +1043,9 @@ static void createAstAtTokenInner(Token * const tok1, const Token *endToken, boo
|
||||||
tok = createAstAtToken(tok, cpp);
|
tok = createAstAtToken(tok, cpp);
|
||||||
} else if (tok->str() == "[") {
|
} else if (tok->str() == "[") {
|
||||||
if (isLambdaCaptureList(tok)) {
|
if (isLambdaCaptureList(tok)) {
|
||||||
|
tok = const_cast<Token *>(tok->astOperand1());
|
||||||
|
if (tok->str() == "(")
|
||||||
|
tok = const_cast<Token *>(tok->astOperand1());
|
||||||
const Token * const endToken2 = tok->link();
|
const Token * const endToken2 = tok->link();
|
||||||
for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->next() : nullptr)
|
for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->next() : nullptr)
|
||||||
tok = createAstAtToken(tok, cpp);
|
tok = createAstAtToken(tok, cpp);
|
||||||
|
|
|
@ -8167,6 +8167,8 @@ private:
|
||||||
ASSERT_EQUALS("{([cd,(return 0return", testAst("return [](int a, int b) -> int { return 0; }(c, d);"));
|
ASSERT_EQUALS("{([cd,(return 0return", testAst("return [](int a, int b) -> int { return 0; }(c, d);"));
|
||||||
|
|
||||||
ASSERT_EQUALS("x{([= 0return", testAst("x = [](){return 0; };"));
|
ASSERT_EQUALS("x{([= 0return", testAst("x = [](){return 0; };"));
|
||||||
|
|
||||||
|
ASSERT_EQUALS("ab{[(= cd=", testAst("a = b([&]{c=d;});"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void compileLimits() {
|
void compileLimits() {
|
||||||
|
|
Loading…
Reference in New Issue