diff --git a/lib/token.cpp b/lib/token.cpp index 9116dd88191..5f151a48e4a 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1578,6 +1578,12 @@ std::pair Token::findExpressionStartEndTokens() co end = goToRightParenthesis(start, end); if (Token::simpleMatch(end, "{")) end = end->link(); + + if (precedes(top, start)) + throw InternalError(start, "Cannot find start of expression"); + if (succeeds(top, end)) + throw InternalError(end, "Cannot find end of expression"); + return std::pair(start,end); } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 98345dd31f9..6bc6d56a929 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -10025,12 +10025,19 @@ void Tokenizer::simplifyOperatorName() } } + const bool returnsRef = Token::simpleMatch(par, "( & (") && tok->next()->isName(); if (par && !op.empty()) { - tok->str("operator" + op); - Token::eraseTokens(tok, par); + if (returnsRef) { + par->next()->insertToken("operator" + op)->isOperatorKeyword(true); + tok->deleteThis(); + } + else { + tok->str("operator" + op); + Token::eraseTokens(tok, par); + } } - if (!op.empty()) + if (!op.empty() && !returnsRef) tok->isOperatorKeyword(true); } diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index b6e312625d9..f59722f21cc 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -646,7 +646,7 @@ static void compileUnaryOp(Token *&tok, AST_state& state, void (*f)(Token *&tok, state.depth--; } - if (!state.op.empty()) { + if (!state.op.empty() && (!precedes(state.op.top(), unaryop) || unaryop->isIncDecOp() || Token::Match(unaryop, "[({[]"))) { // nullary functions, empty lists/arrays unaryop->astOperand1(state.op.top()); state.op.pop(); } diff --git a/test/cli/fuzz-timeout/minimized-from-179e5b42a7b0ba41a088e7972bdb13dde18ef4d1 b/test/cli/fuzz-timeout/minimized-from-179e5b42a7b0ba41a088e7972bdb13dde18ef4d1 new file mode 100644 index 00000000000..9118d58da24 --- /dev/null +++ b/test/cli/fuzz-timeout/minimized-from-179e5b42a7b0ba41a088e7972bdb13dde18ef4d1 @@ -0,0 +1 @@ +d f(*){*:b&&} \ No newline at end of file diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index a63538f346b..bec603a51d7 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -2906,11 +2906,11 @@ class TestSimplifyTypedef : public TestFixture { const char code[] = "class c {\n" " typedef char foo[4];\n" " foo _a;\n" - " constexpr operator foo &() const noexcept { return _a; }\n" + " constexpr operator foo &() noexcept { return _a; }\n" "};"; - const char actual[] = "class c { char _a [ 4 ] ; constexpr operatorchar ( & ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; - const char exp[] = "class c { char _a [ 4 ] ; const operator char ( & ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; + const char actual[] = "class c { char _a [ 4 ] ; constexpr char ( & operatorchar ( ) noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; + const char exp[] = "class c { char _a [ 4 ] ; char ( & operatorchar ( ) noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; TODO_ASSERT_EQUALS(exp, actual, tok(code, false)); } @@ -2921,8 +2921,8 @@ class TestSimplifyTypedef : public TestFixture { " constexpr operator const foo &() const noexcept { return _a; }\n" "};"; - const char actual[] = "class c { char _a [ 4 ] ; constexpr operatorconstchar ( & ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; - const char exp[] = "class c { char _a [ 4 ] ; const operator const char ( & ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; + const char actual[] = "class c { char _a [ 4 ] ; constexpr const char ( & operatorconstchar ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; + const char exp[] = "class c { char _a [ 4 ] ; const char ( & operatorconstchar ( ) const noexcept ( true ) ) [ 4 ] { return _a ; } } ;"; TODO_ASSERT_EQUALS(exp, actual, tok(code, false)); } } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 6fa10173b07..5742249e332 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -5101,7 +5101,7 @@ class TestTokenizer : public TestFixture { " operator A& () { return x_; }\n" " A x_;\n" "};"; - ASSERT_EQUALS("template < typename T >\nstruct B {\n\noperatorT ( & ( ) ) [ 3 ] { return x_ ; }\nT x_ [ 3 ] ;\n} ;", tokenizeAndStringify(code)); + ASSERT_EQUALS("template < typename T >\nstruct B {\n\nT ( & operatorT ( ) ) [ 3 ] { return x_ ; }\nT x_ [ 3 ] ;\n} ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } @@ -6586,6 +6586,7 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("abc;(", testAst("a(b;c)")); ASSERT_EQUALS("x{( forbc;;(", testAst("x({ for(a;b;c){} });")); ASSERT_EQUALS("PT.(", testAst("P->~T();")); // <- The "T" token::function() will be a destructor + ASSERT_EQUALS("double&(4[", testAst("void f(double(&)[4]) {}")); } void asttemplate() { // uninstantiated templates will have <,>,etc..