Skip to content

Commit f502d2a

Browse files
authored
Fix 12373: C++20: AST error with concepts using requires and || (#6415)
1 parent 97115c4 commit f502d2a

2 files changed

Lines changed: 20 additions & 4 deletions

File tree

lib/tokenlist.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,11 +1026,17 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
10261026
else
10271027
compileUnaryOp(tok, state, compileExpression);
10281028
tok = tok2->link()->next();
1029-
} else if (Token::simpleMatch(tok, "( {") && Token::simpleMatch(tok->linkAt(1)->previous(), "; } )") && !Token::Match(tok->previous(), "%name% (")) {
1029+
} else if (Token::simpleMatch(tok->previous(), "requires {")) {
1030+
state.op.push(tok);
1031+
tok = tok->link()->next();
1032+
continue;
1033+
} else if (Token::simpleMatch(tok, "( {") && Token::simpleMatch(tok->linkAt(1)->previous(), "; } )") &&
1034+
!Token::Match(tok->previous(), "%name% (")) {
10301035
state.op.push(tok->next());
10311036
tok = tok->link()->next();
10321037
continue;
1033-
} else if (tok->str() == "(" && (!iscast(tok, state.cpp) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
1038+
} else if (tok->str() == "(" &&
1039+
(!iscast(tok, state.cpp) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
10341040
Token* tok2 = tok;
10351041
tok = tok->next();
10361042
const bool opPrevTopSquare = !state.op.empty() && state.op.top() && state.op.top()->str() == "[";
@@ -1052,7 +1058,8 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
10521058
tok = tok->link()->next();
10531059
if (Token::simpleMatch(tok, "::"))
10541060
compileBinOp(tok, state, compileTerm);
1055-
} else if (iscast(tok, state.cpp) && Token::simpleMatch(tok->link(), ") {") && Token::simpleMatch(tok->link()->linkAt(1), "} [")) {
1061+
} else if (iscast(tok, state.cpp) && Token::simpleMatch(tok->link(), ") {") &&
1062+
Token::simpleMatch(tok->link()->linkAt(1), "} [")) {
10561063
Token *cast = tok;
10571064
tok = tok->link()->next();
10581065
Token *tok1 = tok;
@@ -1074,7 +1081,8 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
10741081
tok = end->next();
10751082
else
10761083
throw InternalError(tok, "Syntax error. Unexpected tokens in initializer.", InternalError::AST);
1077-
} else break;
1084+
} else
1085+
break;
10781086
}
10791087
}
10801088

test/testtokenize.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ class TestTokenizer : public TestFixture {
386386
TEST_CASE(astunaryop);
387387
TEST_CASE(astfunction);
388388
TEST_CASE(asttemplate);
389+
TEST_CASE(astrequires);
389390
TEST_CASE(astcast);
390391
TEST_CASE(astlambda);
391392
TEST_CASE(astcase);
@@ -6684,6 +6685,13 @@ class TestTokenizer : public TestFixture {
66846685
ignore_errout();
66856686
}
66866687

6688+
void astrequires()
6689+
{
6690+
ASSERT_EQUALS("requires{ac::||= ac::", testAst("template <class a> concept b = requires { a::c; } || a::c;"));
6691+
ASSERT_EQUALS("requires{ac::||= a{b{||",
6692+
testAst("template <class a, class b> concept c = requires { a{} || b{}; } || a::c;"));
6693+
}
6694+
66876695
void astcast() {
66886696
ASSERT_EQUALS("ac&(=", testAst("a = (long)&c;"));
66896697
ASSERT_EQUALS("ac*(=", testAst("a = (Foo*)*c;"));

0 commit comments

Comments
 (0)