Skip to content

Commit ad2f713

Browse files
pfultz2danmar
authored andcommitted
Fix issue 9525: Syntax Error: AST broken, 'if' doesn't have two operands inside lambda (#2433)
* Fix issue 9525: Syntax Error: AST broken, 'if' doesn't have two operands inside lambda * Fix incorrect matchers
1 parent de4d44a commit ad2f713

2 files changed

Lines changed: 87 additions & 5 deletions

File tree

lib/tokenlist.cpp

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,47 @@ static bool iscast(const Token *tok)
516516
return false;
517517
}
518518

519+
static const Token* findTypeEnd(const Token* tok)
520+
{
521+
while(Token::Match(tok, "%name%|.|::|<|(|template|decltype|sizeof")) {
522+
if (Token::Match(tok, "(|<"))
523+
tok = tok->link();
524+
if (!tok)
525+
return nullptr;
526+
tok = tok->next();
527+
}
528+
return tok;
529+
}
530+
531+
static const Token * findLambdaEndScope(const Token *tok)
532+
{
533+
if (!Token::simpleMatch(tok, "["))
534+
return nullptr;
535+
tok = tok->link();
536+
if (!Token::Match(tok, "] (|{"))
537+
return nullptr;
538+
tok = tok->linkAt(1);
539+
if (Token::simpleMatch(tok, "}"))
540+
return tok;
541+
if (Token::simpleMatch(tok, ") {"))
542+
return tok->linkAt(1);
543+
if (!Token::simpleMatch(tok, ")"))
544+
return nullptr;
545+
tok = tok->next();
546+
while(Token::Match(tok, "mutable|constexpr|constval|noexcept|.")) {
547+
if (Token::simpleMatch(tok, "noexcept ("))
548+
tok = tok->linkAt(1);
549+
if (Token::simpleMatch(tok, ".")) {
550+
tok = findTypeEnd(tok);
551+
break;
552+
}
553+
tok = tok->next();
554+
}
555+
if (Token::simpleMatch(tok, "{"))
556+
return tok->link();
557+
return nullptr;
558+
}
559+
519560
// int(1), int*(2), ..
520561
static Token * findCppTypeInitPar(Token *tok)
521562
{
@@ -567,7 +608,7 @@ static bool iscpp11init_impl(const Token * const tok)
567608
nameToken = nameToken->link()->previous();
568609

569610
const Token *endtok = nullptr;
570-
if (Token::Match(nameToken, "%name% { !!["))
611+
if (Token::Match(nameToken, "%name%|return {") && (!Token::simpleMatch(nameToken->tokAt(2), "[") || findLambdaEndScope(nameToken->tokAt(2))))
571612
endtok = nameToken->linkAt(1);
572613
else if (Token::Match(nameToken,"%name% <") && Token::simpleMatch(nameToken->linkAt(1),"> {"))
573614
endtok = nameToken->linkAt(1)->linkAt(1);
@@ -584,8 +625,9 @@ static bool iscpp11init_impl(const Token * const tok)
584625
for (const Token *tok2 = nameToken->next(); tok2 != endtok; tok2 = tok2->next()) {
585626
if (tok2->str() == ";")
586627
return false;
587-
if (tok2->str() == "[" && Token::simpleMatch(tok2->link(), "] (") && Token::simpleMatch(tok2->link()->linkAt(1), ") {"))
588-
tok2 = tok2->link()->linkAt(1)->linkAt(1);
628+
const Token * lambdaEnd = findLambdaEndScope(tok2);
629+
if (lambdaEnd)
630+
tok2 = lambdaEnd;
589631
}
590632
}
591633
// There is no initialisation for example here: 'class Fred {};'

test/testtokenize.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7818,18 +7818,30 @@ class TestTokenizer : public TestFixture {
78187818
// 8628
78197819
ASSERT_EQUALS("f{([( switchx( 1case y++", testAst("f([](){switch(x){case 1:{++y;}}});"));
78207820

7821-
ASSERT_EQUALS("{return ab=",
7821+
ASSERT_EQUALS("{([{return ab=",
78227822
testAst("return {\n"
78237823
" [=]() {\n"
78247824
" a = b;\n"
78257825
" }\n"
78267826
"};\n"));
7827-
ASSERT_EQUALS("{return ab=",
7827+
ASSERT_EQUALS("{[{return ab=",
7828+
testAst("return {\n"
7829+
" [=] {\n"
7830+
" a = b;\n"
7831+
" }\n"
7832+
"};\n"));
7833+
ASSERT_EQUALS("{([{return ab=",
78287834
testAst("return {\n"
78297835
" [=]() -> int {\n"
78307836
" a=b;\n"
78317837
" }\n"
78327838
"}"));
7839+
ASSERT_EQUALS("{([{return ab=",
7840+
testAst("return {\n"
7841+
" [=]() mutable -> int {\n"
7842+
" a=b;\n"
7843+
" }\n"
7844+
"}"));
78337845

78347846
// daca@home hang
78357847
ASSERT_EQUALS("a{([= 0return b{([= fori0=i10!=i++;;(",
@@ -8112,6 +8124,34 @@ class TestTokenizer : public TestFixture {
81128124
" auto b = [this, a] {};\n"
81138125
" }\n"
81148126
"};\n"))
8127+
8128+
// #9525
8129+
ASSERT_NO_THROW(tokenizeAndStringify("struct a {\n"
8130+
" template <class b> a(b) {}\n"
8131+
"};\n"
8132+
"auto c() -> a {\n"
8133+
" return {[] {\n"
8134+
" if (0) {}\n"
8135+
" }};\n"
8136+
"}\n"))
8137+
ASSERT_NO_THROW(tokenizeAndStringify("struct a {\n"
8138+
" template <class b> a(b) {}\n"
8139+
"};\n"
8140+
"auto c() -> a {\n"
8141+
" return {[]() -> int {\n"
8142+
" if (0) {}\n"
8143+
" return 0;\n"
8144+
" }};\n"
8145+
"}\n"))
8146+
ASSERT_NO_THROW(tokenizeAndStringify("struct a {\n"
8147+
" template <class b> a(b) {}\n"
8148+
"};\n"
8149+
"auto c() -> a {\n"
8150+
" return {[]() mutable -> int {\n"
8151+
" if (0) {}\n"
8152+
" return 0;\n"
8153+
" }};\n"
8154+
"}\n"))
81158155
}
81168156
void checkIfCppCast() {
81178157
ASSERT_NO_THROW(tokenizeAndStringify("struct a {\n"

0 commit comments

Comments
 (0)