Fixed #3314 (cppcheck incorrectly reporting Syntax error.)
This commit is contained in:
parent
0dad8b64e8
commit
418c2e51a0
|
@ -619,13 +619,34 @@ void Tokenizer::simplifyTypedef()
|
||||||
Token *namespaceEnd = nullptr;
|
Token *namespaceEnd = nullptr;
|
||||||
|
|
||||||
// check for invalid input
|
// check for invalid input
|
||||||
if (!tok->next()) {
|
if (!tokOffset) {
|
||||||
syntaxError(tok);
|
syntaxError(tok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok->next()->str() == "::" || Token::Match(tok->next(), "%type%")) {
|
if (tokOffset->str() == "::") {
|
||||||
typeStart = tok->next();
|
typeStart = tokOffset;
|
||||||
|
tokOffset = tokOffset->next();
|
||||||
|
|
||||||
|
while (Token::Match(tokOffset, "%type% ::"))
|
||||||
|
tokOffset = tokOffset->tokAt(2);
|
||||||
|
|
||||||
|
typeEnd = tokOffset;
|
||||||
|
|
||||||
|
if (Token::Match(tokOffset, "%type%"))
|
||||||
|
tokOffset = tokOffset->next();
|
||||||
|
} else if (Token::Match(tokOffset, "%type% ::")) {
|
||||||
|
typeStart = tokOffset;
|
||||||
|
|
||||||
|
while (Token::Match(tokOffset, "%type% ::"))
|
||||||
|
tokOffset = tokOffset->tokAt(2);
|
||||||
|
|
||||||
|
typeEnd = tokOffset;
|
||||||
|
|
||||||
|
if (Token::Match(tokOffset, "%type%"))
|
||||||
|
tokOffset = tokOffset->next();
|
||||||
|
} else if (Token::Match(tokOffset, "%type%")) {
|
||||||
|
typeStart = tokOffset;
|
||||||
|
|
||||||
while (Token::Match(tokOffset, "const|signed|unsigned|struct|enum %type%") ||
|
while (Token::Match(tokOffset, "const|signed|unsigned|struct|enum %type%") ||
|
||||||
(tokOffset->next() && tokOffset->next()->isStandardType()))
|
(tokOffset->next() && tokOffset->next()->isStandardType()))
|
||||||
|
@ -738,18 +759,6 @@ void Tokenizer::simplifyTypedef()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unhandled function pointer, skip it and continue
|
|
||||||
// TODO: handle such typedefs. See ticket #3314
|
|
||||||
else if (Token::Match(tokOffset, "( %type% ::") &&
|
|
||||||
Token::Match(tokOffset->link()->tokAt(-3), ":: * %var% ) (")) {
|
|
||||||
unsupportedTypedef(typeDef);
|
|
||||||
tok = deleteInvalidTypedef(typeDef);
|
|
||||||
if (tok == list.front())
|
|
||||||
//now the next token to process is 'tok', not 'tok->next()';
|
|
||||||
goback = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// function pointer
|
// function pointer
|
||||||
else if (Token::Match(tokOffset, "( * %var% ) (")) {
|
else if (Token::Match(tokOffset, "( * %var% ) (")) {
|
||||||
// name token wasn't a name, it was part of the type
|
// name token wasn't a name, it was part of the type
|
||||||
|
|
|
@ -117,13 +117,6 @@ private:
|
||||||
const char code[] ="enum ABC { A,B, typedef enum { C } };";
|
const char code[] ="enum ABC { A,B, typedef enum { C } };";
|
||||||
ASSERT_THROW(checkCode(code), InternalError);
|
ASSERT_THROW(checkCode(code), InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
// #3314 - don't report syntax error.
|
|
||||||
const char code[] ="struct A { typedef B::C (A::*f)(); };";
|
|
||||||
checkCode(code);
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (debug) Failed to parse 'typedef B :: C ( A :: * f ) ( ) ;'. The checking continues anyway.\n", errout.str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrong_syntax2() { // #3504
|
void wrong_syntax2() { // #3504
|
||||||
|
|
|
@ -154,6 +154,7 @@ private:
|
||||||
TEST_CASE(simplifyTypedefFunction6);
|
TEST_CASE(simplifyTypedefFunction6);
|
||||||
TEST_CASE(simplifyTypedefFunction7);
|
TEST_CASE(simplifyTypedefFunction7);
|
||||||
TEST_CASE(simplifyTypedefFunction8);
|
TEST_CASE(simplifyTypedefFunction8);
|
||||||
|
TEST_CASE(simplifyTypedefFunction9);
|
||||||
|
|
||||||
TEST_CASE(simplifyTypedefShadow); // #4445 - shadow variable
|
TEST_CASE(simplifyTypedefShadow); // #4445 - shadow variable
|
||||||
}
|
}
|
||||||
|
@ -3033,6 +3034,92 @@ private:
|
||||||
TODO_ASSERT_EQUALS("", "[test.cpp:2]: (debug) Function::addArguments found argument 'int' with varid 0.\n", errout.str()); // make sure that there is no internal error
|
TODO_ASSERT_EQUALS("", "[test.cpp:2]: (debug) Function::addArguments found argument 'int' with varid 0.\n", errout.str()); // make sure that there is no internal error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplifyTypedefFunction9() {
|
||||||
|
{
|
||||||
|
const char code[] = "typedef ::C (::C::* func1)();\n"
|
||||||
|
"typedef ::C (::C::* func2)() const;\n"
|
||||||
|
"typedef ::C (::C::* func3)() volatile;\n"
|
||||||
|
"typedef ::C (::C::* func4)() const volatile;\n"
|
||||||
|
"func1 f1;\n"
|
||||||
|
"func2 f2;\n"
|
||||||
|
"func3 f3;\n"
|
||||||
|
"func4 f4;";
|
||||||
|
|
||||||
|
// The expected result..
|
||||||
|
const std::string expected(":: C ( :: C :: * f1 ) ( ) ; "
|
||||||
|
":: C ( :: C :: * f2 ) ( ) const ; "
|
||||||
|
":: C ( :: C :: * f3 ) ( ) ; "
|
||||||
|
":: C ( :: C :: * f4 ) ( ) const ;");
|
||||||
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
|
|
||||||
|
checkSimplifyTypedef(code);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char code[] = "typedef B::C (B::C::* func1)();\n"
|
||||||
|
"typedef B::C (B::C::* func2)() const;\n"
|
||||||
|
"typedef B::C (B::C::* func3)() volatile;\n"
|
||||||
|
"typedef B::C (B::C::* func4)() const volatile;\n"
|
||||||
|
"func1 f1;\n"
|
||||||
|
"func2 f2;\n"
|
||||||
|
"func3 f3;\n"
|
||||||
|
"func4 f4;";
|
||||||
|
|
||||||
|
// The expected result..
|
||||||
|
const std::string expected("B :: C * f1 ; "
|
||||||
|
"B :: C ( B :: C :: * f2 ) ( ) const ; "
|
||||||
|
"B :: C * f3 ; "
|
||||||
|
"B :: C ( B :: C :: * f4 ) ( ) const ;");
|
||||||
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
|
|
||||||
|
checkSimplifyTypedef(code);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char code[] = "typedef ::B::C (::B::C::* func1)();\n"
|
||||||
|
"typedef ::B::C (::B::C::* func2)() const;\n"
|
||||||
|
"typedef ::B::C (::B::C::* func3)() volatile;\n"
|
||||||
|
"typedef ::B::C (::B::C::* func4)() const volatile;\n"
|
||||||
|
"func1 f1;\n"
|
||||||
|
"func2 f2;\n"
|
||||||
|
"func3 f3;\n"
|
||||||
|
"func4 f4;";
|
||||||
|
|
||||||
|
// The expected result..
|
||||||
|
const std::string expected(":: B :: C ( :: B :: C :: * f1 ) ( ) ; "
|
||||||
|
":: B :: C ( :: B :: C :: * f2 ) ( ) const ; "
|
||||||
|
":: B :: C ( :: B :: C :: * f3 ) ( ) ; "
|
||||||
|
":: B :: C ( :: B :: C :: * f4 ) ( ) const ;");
|
||||||
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
|
|
||||||
|
checkSimplifyTypedef(code);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char code[] = "typedef A::B::C (A::B::C::* func1)();\n"
|
||||||
|
"typedef A::B::C (A::B::C::* func2)() const;\n"
|
||||||
|
"typedef A::B::C (A::B::C::* func3)() volatile;\n"
|
||||||
|
"typedef A::B::C (A::B::C::* func4)() const volatile;\n"
|
||||||
|
"func1 f1;\n"
|
||||||
|
"func2 f2;\n"
|
||||||
|
"func3 f3;\n"
|
||||||
|
"func4 f4;";
|
||||||
|
|
||||||
|
// The expected result..
|
||||||
|
const std::string expected("A :: B :: C * f1 ; "
|
||||||
|
"A :: B :: C ( A :: B :: C :: * f2 ) ( ) const ; "
|
||||||
|
"A :: B :: C * f3 ; "
|
||||||
|
"A :: B :: C ( A :: B :: C :: * f4 ) ( ) const ;");
|
||||||
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
|
|
||||||
|
checkSimplifyTypedef(code);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void simplifyTypedefShadow() { // shadow variable (#4445)
|
void simplifyTypedefShadow() { // shadow variable (#4445)
|
||||||
const char code[] = "typedef struct { int x; } xyz;;\n"
|
const char code[] = "typedef struct { int x; } xyz;;\n"
|
||||||
"void f(){\n"
|
"void f(){\n"
|
||||||
|
|
Loading…
Reference in New Issue