From b33e0e3d27ecbf63f5e8ebb4aa969784add2d0fe Mon Sep 17 00:00:00 2001 From: Ken-Patrick LEHRMANN Date: Mon, 5 Aug 2019 11:17:02 +0200 Subject: [PATCH 1/5] 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. --- lib/tokenize.cpp | 7 ++-- test/testsimplifytypedef.cpp | 66 ++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 2b3df5086a5..acdff39b6b7 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1546,11 +1546,12 @@ void Tokenizer::simplifyTypedef() // skip over function parameters if (tok2->strAt(1) == "(") { tok2 = tok2->linkAt(1); - - if (tok2->strAt(1) == "const") - tok2 = tok2->next(); } + // skip over const/noexcept + while (Token::Match(tok2->next(), "const|noexcept")) + tok2 = tok2->next(); + tok2->insertToken(")"); tok2 = tok2->next(); Token::createMutualLinks(tok2, tok3); diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 0b7d78f4719..f9f9ba7f06b 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -164,6 +164,7 @@ class TestSimplifyTypedef : public TestFixture { 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,71 @@ class TestSimplifyTypedef : public TestFixture { 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" + " foo &f const;\n" + "};"; + + const char exp [] = "class c { char ( & f const ) [ 4 ] ; } ;"; + ASSERT_EQUALS(exp, tok(code, false)); + } + + { + const char code[] = "class c {\n" + " typedef char foo[4];\n" + " foo &f const noexcept;\n" + "};"; + + const char exp [] = "class c { char ( & f const noexcept ) [ 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 exp [] = "class c { char ( & f const noexcept ) [ 4 ] ; } ;"; + ASSERT_EQUALS(exp, 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 exp [] = "class c { char ( & f const noexcept ) [ 4 ] ; } ;"; + ASSERT_EQUALS(exp, tok(code, false)); + } + } + void simplifyTypedefFunction1() { { const char code[] = "typedef void (*my_func)();\n" From 5613abc071e335acbb55fe9267c8389f997e7b90 Mon Sep 17 00:00:00 2001 From: Ken-Patrick LEHRMANN Date: Mon, 5 Aug 2019 14:08:15 +0200 Subject: [PATCH 2/5] 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 ``` --- lib/tokenize.cpp | 4 ++-- test/testsimplifytypedef.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index acdff39b6b7..6c314bfdfa6 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,7 +1544,7 @@ void Tokenizer::simplifyTypedef() tok2 = tok2->tokAt(2); // skip over function parameters - if (tok2->strAt(1) == "(") { + if (tok2->str() == "(" || tok2->strAt(1) == "(") { tok2 = tok2->linkAt(1); } diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index f9f9ba7f06b..cfea682b4d0 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -2594,7 +2594,7 @@ class TestSimplifyTypedef : public TestFixture { " constexpr operator foo &() const noexcept { return _a; }\n" "};"; - const char exp [] = "class c { char ( & f const noexcept ) [ 4 ] ; } ;"; + const char exp [] = "class c { char _a [ 4 ] ; const operatorchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; ASSERT_EQUALS(exp, tok(code, false)); } @@ -2605,7 +2605,7 @@ class TestSimplifyTypedef : public TestFixture { " constexpr operator const foo &() const noexcept { return _a; }\n" "};"; - const char exp [] = "class c { char ( & f const noexcept ) [ 4 ] ; } ;"; + const char exp [] = "class c { char _a [ 4 ] ; const operatorconstchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; ASSERT_EQUALS(exp, tok(code, false)); } } From b6222ece0be6d88a79b4abebefda496ed9191b3d Mon Sep 17 00:00:00 2001 From: Ken-Patrick LEHRMANN Date: Tue, 10 Sep 2019 11:14:05 +0200 Subject: [PATCH 3/5] Replace some ASSERT_EQUALS with TODO_ASSERT_EQUALS when the actual result is still wrong --- test/testsimplifytypedef.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index cfea682b4d0..dbf128ef275 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -2594,8 +2594,9 @@ class TestSimplifyTypedef : public TestFixture { " constexpr operator foo &() const noexcept { return _a; }\n" "};"; - const char exp [] = "class c { char _a [ 4 ] ; const operatorchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; - ASSERT_EQUALS(exp, tok(code, false)); + 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)); } { @@ -2605,8 +2606,9 @@ class TestSimplifyTypedef : public TestFixture { " constexpr operator const foo &() const noexcept { return _a; }\n" "};"; - const char exp [] = "class c { char _a [ 4 ] ; const operatorconstchar ( & ( ) const noexcept ) [ 4 ] { return _a ; } } ;"; - ASSERT_EQUALS(exp, tok(code, false)); + 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)); } } From 8dd8a91e9157482128d0db06d4d40bb40569da11 Mon Sep 17 00:00:00 2001 From: Ken-Patrick LEHRMANN Date: Fri, 11 Oct 2019 09:58:23 +0200 Subject: [PATCH 4/5] Remove invalid code from simplifyTypedef129 --- test/testsimplifytypedef.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index dbf128ef275..30f2555cfec 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -2559,20 +2559,10 @@ class TestSimplifyTypedef : public TestFixture { { const char code[] = "class c {\n" " typedef char foo[4];\n" - " foo &f const;\n" + " const foo &f;\n" "};"; - const char exp [] = "class c { char ( & f const ) [ 4 ] ; } ;"; - ASSERT_EQUALS(exp, tok(code, false)); - } - - { - const char code[] = "class c {\n" - " typedef char foo[4];\n" - " foo &f const noexcept;\n" - "};"; - - const char exp [] = "class c { char ( & f const noexcept ) [ 4 ] ; } ;"; + const char exp [] = "class c { const char ( & f ) [ 4 ] ; } ;"; ASSERT_EQUALS(exp, tok(code, false)); } From e7f0e9b0d10532645a73ecdad5019e3cd4974ff8 Mon Sep 17 00:00:00 2001 From: Ken-Patrick LEHRMANN Date: Fri, 11 Oct 2019 10:03:38 +0200 Subject: [PATCH 5/5] Properly skip parentheses --- lib/tokenize.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 6c314bfdfa6..4c46e6ffbed 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1544,9 +1544,11 @@ void Tokenizer::simplifyTypedef() tok2 = tok2->tokAt(2); // skip over function parameters - if (tok2->str() == "(" || tok2->strAt(1) == "(") { - tok2 = tok2->linkAt(1); - } + if (tok2->str() == "(" ) + tok2 = tok2->link(); + + if (tok2->strAt(1) == "(") + tok2 = tok2->linkAt(1); // skip over const/noexcept while (Token::Match(tok2->next(), "const|noexcept"))