From 5a08ac361a71e9e5641bc376ed908ea42c723bb2 Mon Sep 17 00:00:00 2001 From: KenPatrickLehrmann <54900810+KenPatrickLehrmann@users.noreply.github.com> Date: Sat, 12 Oct 2019 11:46:00 +0200 Subject: [PATCH] Better handle const/noexcept methods (#2211) * Better handle const/noexcept methods/conversion operator const or noexcept in a method / (conversion) operator definition were badly parsed, ending in a bad ast. This patch tries to make it better, at least making the ast less bad, so as to avoid errors in later checks. * Fix parsing of some operator It is still very broken, but at least, it does not fail. Here is the previous error: ``` TestSimplifyTypedef::simplifyTypedef129 terminate called after throwing an instance of 'InternalError' Program received signal SIGABRT, Aborted. __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory. (gdb) bt #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 #1 0x00007ffff612a801 in __GI_abort () at abort.c:79 #2 0x00007ffff6b1d957 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #3 0x00007ffff6b23ab6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #4 0x00007ffff6b23af1 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #5 0x00007ffff6b23d24 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #6 0x0000555556366bf8 in Tokenizer::cppcheckError (this=0x7fffffffc2d0, tok=0x607000006760) at ../lib/tokenize.cpp:8721 #7 0x000055555636a4bb in Tokenizer::validate (this=0x7fffffffc2d0) at ../lib/tokenize.cpp:9154 #8 0x000055555633e3aa in Tokenizer::simplifyTokenList1 (this=0x7fffffffc2d0, FileName=0x603000002d50 "test.cpp") at ../lib/tokenize.cpp:4477 #9 0x00005555563223ca in Tokenizer::simplifyTokens1 (this=0x7fffffffc2d0, configuration="") at ../lib/tokenize.cpp:2286 #10 0x00005555563235c8 in Tokenizer::tokenize (this=0x7fffffffc2d0, code=..., FileName=0x555556fda9a0 "test.cpp", configuration="") at ../lib/tokenize.cpp:2345 #11 0x00005555569410ea in TestSimplifyTypedef::tok[abi:cxx11](char const*, bool, cppcheck::Platform::PlatformType, bool) (this=0x555557728580 <(anonymous namespace)::instance_TestSimplifyTypedef>, code=0x7fffffffcb70 "class c {\n typedef char foo[4];\n foo _a;\n constexpr operator foo &() const noexcept { return _a; }\n};", simplify=false, type=cppcheck::Platform::Native, debugwarnings=true) at ../test/testsimplifytypedef.cpp:192 #12 0x000055555697239e in TestSimplifyTypedef::simplifyTypedef129 (this=0x555557728580 <(anonymous namespace)::instance_TestSimplifyTypedef>) at ../test/testsimplifytypedef.cpp:2599 #13 0x000055555694092c in TestSimplifyTypedef::run (this=0x555557728580 <(anonymous namespace)::instance_TestSimplifyTypedef>) at ../test/testsimplifytypedef.cpp:167 #14 0x00005555569cab84 in TestFixture::run (this=0x555557728580 <(anonymous namespace)::instance_TestSimplifyTypedef>, str="simplifyTypedef129") at ../test/testsuite.cpp:306 #15 0x00005555569cb445 in TestFixture::runTests (args=...) at ../test/testsuite.cpp:329 #16 0x000055555687bdfb in main (argc=2, argv=0x7fffffffd988) at ../test/testrunner.cpp:44 ``` * Replace some ASSERT_EQUALS with TODO_ASSERT_EQUALS when the actual result is still wrong * Remove invalid code from simplifyTypedef129 * Properly skip parentheses --- lib/tokenize.cpp | 15 ++++++---- test/testsimplifytypedef.cpp | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index fc0a73729..8951d5768 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1533,7 +1533,7 @@ void Tokenizer::simplifyTypedef() Token *tok3 = tok2->next(); // handle missing variable name - if (tok2->strAt(3) == ")" || tok2->strAt(3) == ",") + if (tok2->strAt(3) == ")" || tok2->strAt(3) == "," || tok2->strAt(3) == "(") tok2 = tok2->tokAt(2); else tok2 = tok2->tokAt(3); @@ -1544,12 +1544,15 @@ void Tokenizer::simplifyTypedef() tok2 = tok2->tokAt(2); // skip over function parameters - if (tok2->strAt(1) == "(") { - tok2 = tok2->linkAt(1); + if (tok2->str() == "(" ) + tok2 = tok2->link(); - if (tok2->strAt(1) == "const") - tok2 = tok2->next(); - } + if (tok2->strAt(1) == "(") + tok2 = tok2->linkAt(1); + + // skip over const/noexcept + while (Token::Match(tok2->next(), "const|noexcept")) + tok2 = tok2->next(); tok2->insertToken(")"); tok2 = tok2->next(); diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 0b7d78f47..30f2555cf 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -164,6 +164,7 @@ private: TEST_CASE(simplifyTypedef126); // ticket #5953 TEST_CASE(simplifyTypedef127); // ticket #8878 TEST_CASE(simplifyTypedef128); // ticket #9053 + TEST_CASE(simplifyTypedef129); TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -2544,6 +2545,63 @@ private: ASSERT_EQUALS(exp, tok(code, false)); } + void simplifyTypedef129() { + { + const char code[] = "class c {\n" + " typedef char foo[4];\n" + " foo &f ;\n" + "};"; + + const char exp [] = "class c { char ( & f ) [ 4 ] ; } ;"; + ASSERT_EQUALS(exp, tok(code, false)); + } + + { + const char code[] = "class c {\n" + " typedef char foo[4];\n" + " const foo &f;\n" + "};"; + + const char exp [] = "class c { const char ( & f ) [ 4 ] ; } ;"; + ASSERT_EQUALS(exp, tok(code, false)); + } + + { + const char code[] = "class c {\n" + " typedef char foo[4];\n" + " foo _a;\n" + " constexpr const foo &c_str() const noexcept { return _a; }\n" + "};"; + + const char exp [] = "class c { char _a [ 4 ] ; const const char ( & c_str ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + ASSERT_EQUALS(exp, tok(code, false)); + } + + { + const char code[] = "class c {\n" + " typedef char foo[4];\n" + " foo _a;\n" + " constexpr operator foo &() const noexcept { return _a; }\n" + "};"; + + const char actual [] = "class c { char _a [ 4 ] ; const operatorchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char exp [] = "class c { char _a [ 4 ] ; const operator char ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + TODO_ASSERT_EQUALS(exp, actual, tok(code, false)); + } + + { + const char code[] = "class c {\n" + " typedef char foo[4];\n" + " foo _a;\n" + " constexpr operator const foo &() const noexcept { return _a; }\n" + "};"; + + const char actual [] = "class c { char _a [ 4 ] ; const operatorconstchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + const char exp [] = "class c { char _a [ 4 ] ; const operator const char ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; + TODO_ASSERT_EQUALS(exp, actual, tok(code, false)); + } + } + void simplifyTypedefFunction1() { { const char code[] = "typedef void (*my_func)();\n"