Fix issue 9511: Syntax Error: AST broken, 'if' doesn't have two operands. (#2428)
This commit is contained in:
parent
5979eec2c0
commit
2978c67e6f
|
@ -601,6 +601,15 @@ static bool iscpp11init_impl(const Token * const tok)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool isRefQualifier(const Token* tok)
|
||||
{
|
||||
if (!Token::Match(tok, "&|&&"))
|
||||
return false;
|
||||
if (!Token::Match(tok->next(), "{|;"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void compileUnaryOp(Token *&tok, AST_state& state, void(*f)(Token *&tok, AST_state& state))
|
||||
{
|
||||
Token *unaryop = tok;
|
||||
|
@ -1027,7 +1036,7 @@ static void compileAnd(Token *&tok, AST_state& state)
|
|||
{
|
||||
compileEqComp(tok, state);
|
||||
while (tok) {
|
||||
if (tok->str() == "&" && !tok->astOperand1()) {
|
||||
if (tok->str() == "&" && !tok->astOperand1() && !isRefQualifier(tok)) {
|
||||
Token* tok2 = tok->next();
|
||||
if (!tok2)
|
||||
break;
|
||||
|
@ -1066,7 +1075,7 @@ static void compileLogicAnd(Token *&tok, AST_state& state)
|
|||
{
|
||||
compileOr(tok, state);
|
||||
while (tok) {
|
||||
if (tok->str() == "&&") {
|
||||
if (tok->str() == "&&" && !isRefQualifier(tok)) {
|
||||
if (!tok->astOperand1()) {
|
||||
Token* tok2 = tok->next();
|
||||
if (!tok2)
|
||||
|
|
|
@ -456,6 +456,7 @@ private:
|
|||
TEST_CASE(astcast);
|
||||
TEST_CASE(astlambda);
|
||||
TEST_CASE(astcase);
|
||||
TEST_CASE(astrefqualifier);
|
||||
TEST_CASE(astvardecl);
|
||||
|
||||
TEST_CASE(startOfExecutableScope);
|
||||
|
@ -472,6 +473,7 @@ private:
|
|||
TEST_CASE(checkNamespaces);
|
||||
TEST_CASE(checkLambdas);
|
||||
TEST_CASE(checkIfCppCast);
|
||||
TEST_CASE(checkRefQualifiers);
|
||||
|
||||
// #9052
|
||||
TEST_CASE(noCrash1);
|
||||
|
@ -7820,6 +7822,15 @@ private:
|
|||
ASSERT_EQUALS("xyz:?case", testAst("case (x?y:z):"));
|
||||
}
|
||||
|
||||
void astrefqualifier() {
|
||||
ASSERT_EQUALS("b(int.", testAst("class a { auto b() -> int&; };"));
|
||||
ASSERT_EQUALS("b(int.", testAst("class a { auto b() -> int&&; };"));
|
||||
ASSERT_EQUALS("b(", testAst("class a { void b() &&; };"));
|
||||
ASSERT_EQUALS("b(", testAst("class a { void b() &; };"));
|
||||
ASSERT_EQUALS("b(", testAst("class a { void b() && {} };"));
|
||||
ASSERT_EQUALS("b(", testAst("class a { void b() & {} };"));
|
||||
}
|
||||
|
||||
void compileLimits() {
|
||||
const char raw_code[] = "#define PTR1 (* (* (* (* (* (* (* (* (* (*\n"
|
||||
"#define PTR2 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1\n"
|
||||
|
@ -8095,6 +8106,49 @@ private:
|
|||
"}\n"))
|
||||
}
|
||||
|
||||
// #9511
|
||||
void checkRefQualifiers() {
|
||||
ASSERT_NO_THROW(tokenizeAndStringify("class a {\n"
|
||||
" void b() && {\n"
|
||||
" if (this) {}\n"
|
||||
" }\n"
|
||||
"};\n"))
|
||||
ASSERT_NO_THROW(tokenizeAndStringify("class a {\n"
|
||||
" void b() & {\n"
|
||||
" if (this) {}\n"
|
||||
" }\n"
|
||||
"};\n"))
|
||||
ASSERT_NO_THROW(tokenizeAndStringify("class a {\n"
|
||||
" auto b() && -> void {\n"
|
||||
" if (this) {}\n"
|
||||
" }\n"
|
||||
"};\n"))
|
||||
ASSERT_NO_THROW(tokenizeAndStringify("class a {\n"
|
||||
" auto b() & -> void {\n"
|
||||
" if (this) {}\n"
|
||||
" }\n"
|
||||
"};\n"))
|
||||
ASSERT_NO_THROW(tokenizeAndStringify("class a {\n"
|
||||
" auto b(int& x) -> int& {\n"
|
||||
" if (this) {}\n"
|
||||
" return x;\n"
|
||||
" }\n"
|
||||
"};\n"))
|
||||
ASSERT_NO_THROW(tokenizeAndStringify("class a {\n"
|
||||
" auto b(int& x) -> int&& {\n"
|
||||
" if (this) {}\n"
|
||||
" return x;\n"
|
||||
" }\n"
|
||||
"};\n"))
|
||||
ASSERT_NO_THROW(tokenizeAndStringify("class a {\n"
|
||||
" auto b(int& x) && -> int& {\n"
|
||||
" if (this) {}\n"
|
||||
" return x;\n"
|
||||
" }\n"
|
||||
"};\n"))
|
||||
|
||||
}
|
||||
|
||||
void noCrash1() {
|
||||
ASSERT_NO_THROW(tokenizeAndStringify(
|
||||
"struct A {\n"
|
||||
|
|
Loading…
Reference in New Issue