diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index a4b00bce7..aaf8dd576 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -10804,12 +10804,15 @@ void Tokenizer::deleteSymbolDatabase() mSymbolDatabase = nullptr; } -static bool operatorEnd(const Token * tok) +bool Tokenizer::operatorEnd(const Token * tok) const { if (tok && tok->str() == ")") { + if (isFunctionHead(tok, "{|;")) + return true; + tok = tok->next(); while (tok && !Token::Match(tok, "[=;{),]")) { - if (Token::Match(tok, "const|volatile")) { + if (Token::Match(tok, "const|volatile|override")) { tok = tok->next(); } else if (tok->str() == "noexcept") { tok = tok->next(); @@ -10825,7 +10828,10 @@ static bool operatorEnd(const Token * tok) if (tok && tok->str() == "(") { tok = tok->link()->next(); } - } else + } else if (Token::Match(tok, "%op% !!(") || + (Token::Match(tok, "%op% (") && !isFunctionHead(tok->next(), "{"))) + break; + else return false; } @@ -10893,11 +10899,11 @@ void Tokenizer::simplifyOperatorName() par = par->tokAt(2); done = true; } else if (par->str() != "(") { - syntaxError(par); + syntaxError(par, "operator"); } } - if (par && (Token::Match(par, "<|>") || isFunctionHead(par, "{|;"))) { + if (par && !op.empty()) { tok->str("operator" + op); Token::eraseTokens(tok, par); } diff --git a/lib/tokenize.h b/lib/tokenize.h index b4a0d9cef..320add03e 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -797,6 +797,8 @@ private: /** Find end of SQL (or PL/SQL) block */ static const Token *findSQLBlockEnd(const Token *tokSQLStart); + bool operatorEnd(const Token * tok) const; + public: /** Was there templates in the code? */ diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 001db7723..4ce772b7e 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -1627,12 +1627,8 @@ private: } void garbageCode206() { - { - ASSERT_EQUALS("[test.cpp:1] syntax error", getSyntaxError("void foo() { for (auto operator new : int); }")); - } - { - ASSERT_EQUALS("[test.cpp:1] syntax error", getSyntaxError("void foo() { for (a operator== :) }")); - } + ASSERT_EQUALS("[test.cpp:1] syntax error: operator", getSyntaxError("void foo() { for (auto operator new : int); }")); + ASSERT_EQUALS("[test.cpp:1] syntax error: operator", getSyntaxError("void foo() { for (a operator== :) }")); } void syntaxErrorFirstToken() { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index f371af934..33fa15767 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -400,6 +400,8 @@ private: TEST_CASE(simplifyOperatorName13); // user defined literal TEST_CASE(simplifyOperatorName14); // std::complex operator "" if TEST_CASE(simplifyOperatorName15); // ticket #9468 syntaxError + TEST_CASE(simplifyOperatorName16); // ticket #9472 + TEST_CASE(simplifyOperatorName17); TEST_CASE(simplifyNullArray); @@ -6394,6 +6396,52 @@ private: tokenizeAndStringify(code)); } + void simplifyOperatorName16() { // ticket #9472 + { + const char code[] = "class I : public A { iterator& operator++() override; };"; + ASSERT_EQUALS("class I : public A { iterator & operator++ ( ) override ; } ;", + tokenizeAndStringify(code)); + } + { + const char code[] = "class I : public A { iterator& operator++() override { } };"; + ASSERT_EQUALS("class I : public A { iterator & operator++ ( ) override { } } ;", + tokenizeAndStringify(code)); + } + } + + void simplifyOperatorName17() { + { + const char code[] = "template void b(a c, a d) { c.operator>() == d; }"; + ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator> ( ) == d ; }", + tokenizeAndStringify(code)); + } + { + const char code[] = "template void b(a c, a d) { c.operator>() == (d + 1); }"; + ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator> ( ) == ( d + 1 ) ; }", + tokenizeAndStringify(code)); + } + { + const char code[] = "template void b(a c, a d) { c.operator<() == d; }"; + ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator< ( ) == d ; }", + tokenizeAndStringify(code)); + } + { + const char code[] = "template void b(a c, a d) { c.operator>() == (d + 1); }"; + ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator> ( ) == ( d + 1 ) ; }", + tokenizeAndStringify(code)); + } + { + const char code[] = "template void b(a c, a d) { c.operator++() == d; }"; + ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator++ ( ) == d ; }", + tokenizeAndStringify(code)); + } + { + const char code[] = "template void b(a c, a d) { c.operator++() == (d + 1); }"; + ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator++ ( ) == ( d + 1 ) ; }", + tokenizeAndStringify(code)); + } + } + void simplifyNullArray() { ASSERT_EQUALS("* ( foo . bar [ 5 ] ) = x ;", tokenizeAndStringify("0[foo.bar[5]] = x;")); }