Skip to content

Commit f9ca1b4

Browse files
Fix #15008 internalAstError for c++23 lambda (#8821)
Co-authored-by: chrchr-github <noreply@github.com>
1 parent f695ade commit f9ca1b4

4 files changed

Lines changed: 26 additions & 14 deletions

File tree

lib/astutils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3304,12 +3304,12 @@ static T* findLambdaEndTokenGeneric(T* first)
33043304
return nullptr;
33053305
if (!maybeLambda(first->previous()))
33063306
return nullptr;
3307-
if (!Token::Match(first->link(), "] (|{|<"))
3307+
if (!Token::Match(first->link(), "] [({<.]"))
33083308
return nullptr;
33093309
const Token* roundOrCurly = first->link()->next();
33103310
if (roundOrCurly->link() && roundOrCurly->str() == "<")
33113311
roundOrCurly = roundOrCurly->link()->next();
3312-
if (first->astOperand1() != roundOrCurly)
3312+
if (first->astOperand1() != roundOrCurly && roundOrCurly->str() != ".")
33133313
return nullptr;
33143314
T * tok = first;
33153315

lib/tokenlist.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,21 @@ static bool isPrefixUnary(const Token* tok, bool cpp)
969969
return tok->strAt(-1) == ")" && iscast(tok->linkAt(-1), cpp);
970970
}
971971

972+
template<class T, REQUIRES("T must be a Token class", std::is_convertible<T*, const Token*> )>
973+
static T* skipTrailingReturnType(T* tok)
974+
{
975+
if (!Token::Match(tok, ".|->")) // TODO: fix simplification (see garbageCode228)
976+
return tok;
977+
tok = tok->next();
978+
while (Token::Match(tok, "%type%|%name%|::|&|&&|*|<|(")) {
979+
if (tok->link())
980+
tok = tok->link()->next();
981+
else
982+
tok = tok->next();
983+
}
984+
return tok;
985+
}
986+
972987
/**
973988
* @throws InternalError thrown if unexpected tokens are encountered
974989
*/
@@ -1013,7 +1028,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
10131028
else
10141029
compileUnaryOp(tok, state, compileScope);
10151030
} else if (tok->str() == "[") {
1016-
if (state.cpp && isPrefixUnary(tok, /*cpp*/ true) && Token::Match(tok->link(), "] (|{|<")) { // Lambda
1031+
if (state.cpp && isPrefixUnary(tok, /*cpp*/ true) && Token::Match(tok->link(), "] [({<.]")) { // Lambda
10171032
// What we do here:
10181033
// - Nest the round bracket under the square bracket.
10191034
// - Nest what follows the lambda (if anything) with the lambda opening [
@@ -1062,7 +1077,10 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
10621077
continue;
10631078
}
10641079
} else {
1065-
Token* const curlyBracket = squareBracket->link()->next();
1080+
Token* curlyBracket = squareBracket->link()->next();
1081+
curlyBracket = skipTrailingReturnType(curlyBracket);
1082+
if (!Token::simpleMatch(curlyBracket, "{"))
1083+
throw InternalError(tok, "Syntax error in lambda", InternalError::AST);
10661084
squareBracket->astOperand1(curlyBracket);
10671085
state.op.push(squareBracket);
10681086
tok = curlyBracket->link() ? curlyBracket->link()->next() : nullptr;
@@ -1507,15 +1525,7 @@ const Token* findLambdaEndTokenWithoutAST(const Token* tok) {
15071525
tok = tok->link()->next();
15081526
if (Token::simpleMatch(tok, "mutable"))
15091527
tok = tok->next();
1510-
if (Token::Match(tok, ".|->")) { // trailing return type
1511-
tok = tok->next();
1512-
while (Token::Match(tok, "%type%|%name%|::|&|&&|*|<|(")) {
1513-
if (tok->link())
1514-
tok = tok->link()->next();
1515-
else
1516-
tok = tok->next();
1517-
}
1518-
}
1528+
tok = skipTrailingReturnType(tok);
15191529
if (!(Token::simpleMatch(tok, "{") && tok->link()))
15201530
return nullptr;
15211531
return tok->link()->next();

test/testtokenize.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7664,6 +7664,8 @@ class TestTokenizer : public TestFixture {
76647664
ASSERT_EQUALS("sf.{(i[{={", testAst("void g(int i) { S s{ .f = { [i]() {} } }; }\n"));
76657665

76667666
ASSERT_EQUALS("{([", testAst("void f() { []() {}; }\n")); // #13471
7667+
7668+
ASSERT_EQUALS("x{=[= 0return", testAst("void f() { auto x = [=] -> int { return 0; }; }\n")); // #15008
76677669
}
76687670

76697671
void astcase() {

test/testvalueflow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8097,7 +8097,7 @@ class TestValueFlow : public TestFixture {
80978097
code = "void f(int& r) {\n" // #13515
80988098
" [0].p = &r;\n"
80998099
"}\n";
8100-
(void)valueOfTok(code, "=");
8100+
ASSERT_THROW_INTERNAL(valueOfTok(code, "="), AST);
81018101
}
81028102

81038103
void valueFlowCrash() {

0 commit comments

Comments
 (0)