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
This commit is contained in:
KenPatrickLehrmann 2019-10-12 11:46:00 +02:00 committed by Daniel Marjamäki
parent 19cf636a4a
commit 5a08ac361a
2 changed files with 67 additions and 6 deletions

View File

@ -1533,7 +1533,7 @@ void Tokenizer::simplifyTypedef()
Token *tok3 = tok2->next(); Token *tok3 = tok2->next();
// handle missing variable name // 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); tok2 = tok2->tokAt(2);
else else
tok2 = tok2->tokAt(3); tok2 = tok2->tokAt(3);
@ -1544,12 +1544,15 @@ void Tokenizer::simplifyTypedef()
tok2 = tok2->tokAt(2); tok2 = tok2->tokAt(2);
// skip over function parameters // skip over function parameters
if (tok2->strAt(1) == "(") { if (tok2->str() == "(" )
tok2 = tok2->link();
if (tok2->strAt(1) == "(")
tok2 = tok2->linkAt(1); tok2 = tok2->linkAt(1);
if (tok2->strAt(1) == "const") // skip over const/noexcept
while (Token::Match(tok2->next(), "const|noexcept"))
tok2 = tok2->next(); tok2 = tok2->next();
}
tok2->insertToken(")"); tok2->insertToken(")");
tok2 = tok2->next(); tok2 = tok2->next();

View File

@ -164,6 +164,7 @@ private:
TEST_CASE(simplifyTypedef126); // ticket #5953 TEST_CASE(simplifyTypedef126); // ticket #5953
TEST_CASE(simplifyTypedef127); // ticket #8878 TEST_CASE(simplifyTypedef127); // ticket #8878
TEST_CASE(simplifyTypedef128); // ticket #9053 TEST_CASE(simplifyTypedef128); // ticket #9053
TEST_CASE(simplifyTypedef129);
TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction1);
TEST_CASE(simplifyTypedefFunction2); // ticket #1685 TEST_CASE(simplifyTypedefFunction2); // ticket #1685
@ -2544,6 +2545,63 @@ private:
ASSERT_EQUALS(exp, tok(code, false)); 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() { void simplifyTypedefFunction1() {
{ {
const char code[] = "typedef void (*my_func)();\n" const char code[] = "typedef void (*my_func)();\n"