Skip to content

Commit 418c2e5

Browse files
IOBYTEdanmar
authored andcommitted
Fixed danmar#3314 (cppcheck incorrectly reporting Syntax error.)
1 parent 0dad8b6 commit 418c2e5

File tree

3 files changed

+111
-22
lines changed

3 files changed

+111
-22
lines changed

lib/tokenize.cpp

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -619,13 +619,34 @@ void Tokenizer::simplifyTypedef()
619619
Token *namespaceEnd = nullptr;
620620

621621
// check for invalid input
622-
if (!tok->next()) {
622+
if (!tokOffset) {
623623
syntaxError(tok);
624624
return;
625625
}
626626

627-
if (tok->next()->str() == "::" || Token::Match(tok->next(), "%type%")) {
628-
typeStart = tok->next();
627+
if (tokOffset->str() == "::") {
628+
typeStart = tokOffset;
629+
tokOffset = tokOffset->next();
630+
631+
while (Token::Match(tokOffset, "%type% ::"))
632+
tokOffset = tokOffset->tokAt(2);
633+
634+
typeEnd = tokOffset;
635+
636+
if (Token::Match(tokOffset, "%type%"))
637+
tokOffset = tokOffset->next();
638+
} else if (Token::Match(tokOffset, "%type% ::")) {
639+
typeStart = tokOffset;
640+
641+
while (Token::Match(tokOffset, "%type% ::"))
642+
tokOffset = tokOffset->tokAt(2);
643+
644+
typeEnd = tokOffset;
645+
646+
if (Token::Match(tokOffset, "%type%"))
647+
tokOffset = tokOffset->next();
648+
} else if (Token::Match(tokOffset, "%type%")) {
649+
typeStart = tokOffset;
629650

630651
while (Token::Match(tokOffset, "const|signed|unsigned|struct|enum %type%") ||
631652
(tokOffset->next() && tokOffset->next()->isStandardType()))
@@ -738,18 +759,6 @@ void Tokenizer::simplifyTypedef()
738759
continue;
739760
}
740761

741-
// unhandled function pointer, skip it and continue
742-
// TODO: handle such typedefs. See ticket #3314
743-
else if (Token::Match(tokOffset, "( %type% ::") &&
744-
Token::Match(tokOffset->link()->tokAt(-3), ":: * %var% ) (")) {
745-
unsupportedTypedef(typeDef);
746-
tok = deleteInvalidTypedef(typeDef);
747-
if (tok == list.front())
748-
//now the next token to process is 'tok', not 'tok->next()';
749-
goback = true;
750-
continue;
751-
}
752-
753762
// function pointer
754763
else if (Token::Match(tokOffset, "( * %var% ) (")) {
755764
// name token wasn't a name, it was part of the type

test/testgarbage.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,6 @@ class TestGarbage : public TestFixture {
117117
const char code[] ="enum ABC { A,B, typedef enum { C } };";
118118
ASSERT_THROW(checkCode(code), InternalError);
119119
}
120-
121-
{
122-
// #3314 - don't report syntax error.
123-
const char code[] ="struct A { typedef B::C (A::*f)(); };";
124-
checkCode(code);
125-
ASSERT_EQUALS("[test.cpp:1]: (debug) Failed to parse 'typedef B :: C ( A :: * f ) ( ) ;'. The checking continues anyway.\n", errout.str());
126-
}
127120
}
128121

129122
void wrong_syntax2() { // #3504

test/testsimplifytypedef.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ class TestSimplifyTypedef : public TestFixture {
154154
TEST_CASE(simplifyTypedefFunction6);
155155
TEST_CASE(simplifyTypedefFunction7);
156156
TEST_CASE(simplifyTypedefFunction8);
157+
TEST_CASE(simplifyTypedefFunction9);
157158

158159
TEST_CASE(simplifyTypedefShadow); // #4445 - shadow variable
159160
}
@@ -3033,6 +3034,92 @@ class TestSimplifyTypedef : public TestFixture {
30333034
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
30343035
}
30353036

3037+
void simplifyTypedefFunction9() {
3038+
{
3039+
const char code[] = "typedef ::C (::C::* func1)();\n"
3040+
"typedef ::C (::C::* func2)() const;\n"
3041+
"typedef ::C (::C::* func3)() volatile;\n"
3042+
"typedef ::C (::C::* func4)() const volatile;\n"
3043+
"func1 f1;\n"
3044+
"func2 f2;\n"
3045+
"func3 f3;\n"
3046+
"func4 f4;";
3047+
3048+
// The expected result..
3049+
const std::string expected(":: C ( :: C :: * f1 ) ( ) ; "
3050+
":: C ( :: C :: * f2 ) ( ) const ; "
3051+
":: C ( :: C :: * f3 ) ( ) ; "
3052+
":: C ( :: C :: * f4 ) ( ) const ;");
3053+
ASSERT_EQUALS(expected, tok(code));
3054+
3055+
checkSimplifyTypedef(code);
3056+
ASSERT_EQUALS("", errout.str());
3057+
}
3058+
3059+
{
3060+
const char code[] = "typedef B::C (B::C::* func1)();\n"
3061+
"typedef B::C (B::C::* func2)() const;\n"
3062+
"typedef B::C (B::C::* func3)() volatile;\n"
3063+
"typedef B::C (B::C::* func4)() const volatile;\n"
3064+
"func1 f1;\n"
3065+
"func2 f2;\n"
3066+
"func3 f3;\n"
3067+
"func4 f4;";
3068+
3069+
// The expected result..
3070+
const std::string expected("B :: C * f1 ; "
3071+
"B :: C ( B :: C :: * f2 ) ( ) const ; "
3072+
"B :: C * f3 ; "
3073+
"B :: C ( B :: C :: * f4 ) ( ) const ;");
3074+
ASSERT_EQUALS(expected, tok(code));
3075+
3076+
checkSimplifyTypedef(code);
3077+
ASSERT_EQUALS("", errout.str());
3078+
}
3079+
3080+
{
3081+
const char code[] = "typedef ::B::C (::B::C::* func1)();\n"
3082+
"typedef ::B::C (::B::C::* func2)() const;\n"
3083+
"typedef ::B::C (::B::C::* func3)() volatile;\n"
3084+
"typedef ::B::C (::B::C::* func4)() const volatile;\n"
3085+
"func1 f1;\n"
3086+
"func2 f2;\n"
3087+
"func3 f3;\n"
3088+
"func4 f4;";
3089+
3090+
// The expected result..
3091+
const std::string expected(":: B :: C ( :: B :: C :: * f1 ) ( ) ; "
3092+
":: B :: C ( :: B :: C :: * f2 ) ( ) const ; "
3093+
":: B :: C ( :: B :: C :: * f3 ) ( ) ; "
3094+
":: B :: C ( :: B :: C :: * f4 ) ( ) const ;");
3095+
ASSERT_EQUALS(expected, tok(code));
3096+
3097+
checkSimplifyTypedef(code);
3098+
ASSERT_EQUALS("", errout.str());
3099+
}
3100+
3101+
{
3102+
const char code[] = "typedef A::B::C (A::B::C::* func1)();\n"
3103+
"typedef A::B::C (A::B::C::* func2)() const;\n"
3104+
"typedef A::B::C (A::B::C::* func3)() volatile;\n"
3105+
"typedef A::B::C (A::B::C::* func4)() const volatile;\n"
3106+
"func1 f1;\n"
3107+
"func2 f2;\n"
3108+
"func3 f3;\n"
3109+
"func4 f4;";
3110+
3111+
// The expected result..
3112+
const std::string expected("A :: B :: C * f1 ; "
3113+
"A :: B :: C ( A :: B :: C :: * f2 ) ( ) const ; "
3114+
"A :: B :: C * f3 ; "
3115+
"A :: B :: C ( A :: B :: C :: * f4 ) ( ) const ;");
3116+
ASSERT_EQUALS(expected, tok(code));
3117+
3118+
checkSimplifyTypedef(code);
3119+
ASSERT_EQUALS("", errout.str());
3120+
}
3121+
}
3122+
30363123
void simplifyTypedefShadow() { // shadow variable (#4445)
30373124
const char code[] = "typedef struct { int x; } xyz;;\n"
30383125
"void f(){\n"

0 commit comments

Comments
 (0)