Skip to content

Commit

Permalink
Fix 12373: C++20: AST error with concepts using requires and || (#6415)
Browse files Browse the repository at this point in the history
  • Loading branch information
pfultz2 authored May 22, 2024
1 parent 97115c4 commit f502d2a
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
16 changes: 12 additions & 4 deletions lib/tokenlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1026,11 +1026,17 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
else
compileUnaryOp(tok, state, compileExpression);
tok = tok2->link()->next();
} else if (Token::simpleMatch(tok, "( {") && Token::simpleMatch(tok->linkAt(1)->previous(), "; } )") && !Token::Match(tok->previous(), "%name% (")) {
} else if (Token::simpleMatch(tok->previous(), "requires {")) {
state.op.push(tok);
tok = tok->link()->next();
continue;
} else if (Token::simpleMatch(tok, "( {") && Token::simpleMatch(tok->linkAt(1)->previous(), "; } )") &&
!Token::Match(tok->previous(), "%name% (")) {
state.op.push(tok->next());
tok = tok->link()->next();
continue;
} else if (tok->str() == "(" && (!iscast(tok, state.cpp) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
} else if (tok->str() == "(" &&
(!iscast(tok, state.cpp) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
Token* tok2 = tok;
tok = tok->next();
const bool opPrevTopSquare = !state.op.empty() && state.op.top() && state.op.top()->str() == "[";
Expand All @@ -1052,7 +1058,8 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
tok = tok->link()->next();
if (Token::simpleMatch(tok, "::"))
compileBinOp(tok, state, compileTerm);
} else if (iscast(tok, state.cpp) && Token::simpleMatch(tok->link(), ") {") && Token::simpleMatch(tok->link()->linkAt(1), "} [")) {
} else if (iscast(tok, state.cpp) && Token::simpleMatch(tok->link(), ") {") &&
Token::simpleMatch(tok->link()->linkAt(1), "} [")) {
Token *cast = tok;
tok = tok->link()->next();
Token *tok1 = tok;
Expand All @@ -1074,7 +1081,8 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
tok = end->next();
else
throw InternalError(tok, "Syntax error. Unexpected tokens in initializer.", InternalError::AST);
} else break;
} else
break;
}
}

Expand Down
8 changes: 8 additions & 0 deletions test/testtokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ class TestTokenizer : public TestFixture {
TEST_CASE(astunaryop);
TEST_CASE(astfunction);
TEST_CASE(asttemplate);
TEST_CASE(astrequires);
TEST_CASE(astcast);
TEST_CASE(astlambda);
TEST_CASE(astcase);
Expand Down Expand Up @@ -6684,6 +6685,13 @@ class TestTokenizer : public TestFixture {
ignore_errout();
}

void astrequires()
{
ASSERT_EQUALS("requires{ac::||= ac::", testAst("template <class a> concept b = requires { a::c; } || a::c;"));
ASSERT_EQUALS("requires{ac::||= a{b{||",
testAst("template <class a, class b> concept c = requires { a{} || b{}; } || a::c;"));
}

void astcast() {
ASSERT_EQUALS("ac&(=", testAst("a = (long)&c;"));
ASSERT_EQUALS("ac*(=", testAst("a = (Foo*)*c;"));
Expand Down

0 comments on commit f502d2a

Please sign in to comment.