Fix #9472 (Syntax error on valid C++ code) (#2363)

There are probably a lot more valid code patterns that generates syntax
errors so I added "operator" to the error message to make it easier to
find them.
This commit is contained in:
IOBYTE 2019-11-15 01:03:57 -05:00 committed by amai2012
parent 7e0fc4fb00
commit 3a617fa04a
4 changed files with 63 additions and 11 deletions

View File

@ -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);
}

View File

@ -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? */

View File

@ -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() {

View File

@ -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 <class a> 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 <class a> 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 <class a> 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 <class a> 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 <class a> 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 <class a> 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;"));
}