From ba0b3e6451e33bf4bd5f8220bcc5fa1a0204f199 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Tue, 15 Mar 2011 19:24:30 -0400 Subject: [PATCH 1/5] fix #2651 function typedef with extra ()s --- lib/tokenize.cpp | 15 ++++++++++++--- test/testsimplifytokens.cpp | 10 ++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 734a5bcdd..3d34aa61f 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1234,10 +1234,17 @@ void Tokenizer::simplifyTypedef() } // function: typedef ... ( .... type )( ... ); - else if (tok->tokAt(offset)->str() == "(" && - Token::Match(tok->tokAt(offset)->link()->previous(), "%type% ) (") && - Token::Match(tok->tokAt(offset)->link()->next()->link(), ") const|volatile|;")) + // typedef ... (( .... type )( ... )); + else if ((tok->tokAt(offset)->str() == "(" && + Token::Match(tok->tokAt(offset)->link()->previous(), "%type% ) (") && + Token::Match(tok->tokAt(offset)->link()->next()->link(), ") const|volatile|;")) || + (Token::simpleMatch(tok->tokAt(offset), "( (") && + Token::Match(tok->tokAt(offset + 1)->link()->previous(), "%type% ) (") && + Token::Match(tok->tokAt(offset + 1)->link()->next()->link(), ") const|volatile| )"))) { + if (tok->strAt(offset + 1) == "(") + offset++; + funcStart = tok->tokAt(offset + 1); funcEnd = tok->tokAt(offset)->link()->tokAt(-2); typeName = tok->tokAt(offset)->link()->previous(); @@ -1256,6 +1263,8 @@ void Tokenizer::simplifyTypedef() } tok = specEnd->next(); } + if (tok->str() == ")") + tok = tok->next(); } else if (Token::Match(tok->tokAt(offset), "( %type% (")) diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 74adc52af..ae77e430a 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -246,6 +246,7 @@ private: TEST_CASE(simplifyTypedef82); // ticket #2403 TEST_CASE(simplifyTypedef83); // ticket #2620 TEST_CASE(simplifyTypedef84); // ticket #2630 + TEST_CASE(simplifyTypedef85); // ticket #2651 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -4986,6 +4987,15 @@ private: ASSERT_EQUALS("[test.cpp:1]: (error) syntax error\n", errout.str()); } + void simplifyTypedef85() // ticket #2651 + { + const char code[] = "typedef FOO ((BAR)(void, int, const int, int*));\n"; + const char expected[] = ";"; + checkSimplifyTypedef(code); + ASSERT_EQUALS(expected, sizeof_(code)); + ASSERT_EQUALS("", errout.str()); + } + void simplifyTypedefFunction1() { { From 47531dd99c6bac74609cfaa5cebad87f04dfa7e8 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Tue, 15 Mar 2011 22:33:14 -0400 Subject: [PATCH 2/5] fix #2637 (segmentation fault of cppcheck ( {} const const )) --- lib/symboldatabase.cpp | 5 ++++- test/testclass.cpp | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index a7edd4e41..f7574c63b 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1467,6 +1467,9 @@ void Scope::getVariableList() continue; tok = checkVariable(tok, varaccess); + + if (!tok) + break; } } @@ -1515,7 +1518,7 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess) bool isArray = false; - if (isVariableDeclaration(tok, vartok, typetok, isArray)) + if (tok && isVariableDeclaration(tok, vartok, typetok, isArray)) { isClass = (!typetok->isStandardType() && vartok->previous()->str() != "*"); tok = vartok->next(); diff --git a/test/testclass.cpp b/test/testclass.cpp index 45a9f22a7..7147ebee5 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -196,6 +196,7 @@ private: TEST_CASE(symboldatabase13); // ticket #2577 TEST_CASE(symboldatabase14); // ticket #2589 TEST_CASE(symboldatabase15); // ticket #2591 + TEST_CASE(symboldatabase16); // ticket #2637 } // Check the operator Equal @@ -5791,6 +5792,14 @@ private: ASSERT_EQUALS("", errout.str()); } + void symboldatabase16() + { + // ticket #2637 - segmentation fault + checkConst("{} const const\n"); + + ASSERT_EQUALS("", errout.str()); + } + }; REGISTER_TEST(TestClass) From f7cbc90c847e691738a767585597d1e25d57d810 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Tue, 15 Mar 2011 23:28:45 -0400 Subject: [PATCH 3/5] fix #2581 (### Internal error in Cppcheck. Please report it.) --- lib/tokenize.cpp | 15 ++++++++++++++- test/testsimplifytokens.cpp | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 3d34aa61f..226b19d39 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1245,6 +1245,10 @@ void Tokenizer::simplifyTypedef() if (tok->strAt(offset + 1) == "(") offset++; + if (tok->tokAt(offset)->link()->strAt(-2) == "*") + functionPtr = true; + else + function = true; funcStart = tok->tokAt(offset + 1); funcEnd = tok->tokAt(offset)->link()->tokAt(-2); typeName = tok->tokAt(offset)->link()->previous(); @@ -1528,6 +1532,15 @@ void Tokenizer::simplifyTypedef() if (simplifyType) { + // can't simplify 'operator functionPtr ()' and 'functionPtr operator ... ()' + if (functionPtr && (tok2->previous()->str() == "operator" || + tok2->next()->str() == "operator")) + { + simplifyType = false; + tok2 = tok2->next(); + break; + } + // There are 2 categories of typedef substitutions: // 1. variable declarations that preserve the variable name like // global, local, and function parameters @@ -9472,7 +9485,7 @@ void Tokenizer::simplifyOperatorName() par = par->next(); done = false; } - if (Token::Match(par, "[<>+-*&/=.]") || Token::Match(par, "==|!=|<=|>=")) + if (Token::Match(par, "[<>+-*&/=.!]") || Token::Match(par, "==|!=|<=|>=")) { op += par->str(); par = par->next(); diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index ae77e430a..e188946fd 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -247,6 +247,7 @@ private: TEST_CASE(simplifyTypedef83); // ticket #2620 TEST_CASE(simplifyTypedef84); // ticket #2630 TEST_CASE(simplifyTypedef85); // ticket #2651 + TEST_CASE(simplifyTypedef86); // ticket #2581 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -4996,6 +4997,25 @@ private: ASSERT_EQUALS("", errout.str()); } + void simplifyTypedef86() // ticket #2581 + { + const char code[] = "class relational {\n" + " typedef void (safe_bool_helper::*safe_bool)();\n" + "public:\n" + " operator safe_bool() const;\n" + " safe_bool operator!() const;\n" + "};\n"; + const char expected[] = "class relational { " + "; " + "public: " + "operatorsafe_bool ( ) const ; " + "safe_bool operator! ( ) const ; " + "} ;"; + checkSimplifyTypedef(code); + ASSERT_EQUALS(expected, sizeof_(code)); + ASSERT_EQUALS("", errout.str()); + } + void simplifyTypedefFunction1() { { From fec9edf62850c82f3ef73c108da8cf76364ffcb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 16 Mar 2011 22:16:30 +0100 Subject: [PATCH 4/5] Tokenizer::simplifyTemplates: First simple fix for problems when using sizeof in template parameter --- lib/tokenize.cpp | 19 +++++++++++++++++++ test/testsimplifytokens.cpp | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 226b19d39..dfeb252f5 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2977,6 +2977,25 @@ void Tokenizer::simplifyTemplatesInstantiate(const Token *tok, if (tok2->str() != name) continue; + // #2648 - simple fix for sizeof used as template parameter + // TODO: this is a bit hardcoded. make a bit more generic + if (Token::Match(tok2, "%var% < sizeof ( %type% ) >") && tok2->tokAt(4)->isStandardType()) + { + // make sure standard types have a known size.. + _typeSize["char"] = sizeof(char); + _typeSize["short"] = sizeof(short); + _typeSize["int"] = sizeof(int); + _typeSize["long"] = sizeof(long); + _typeSize["float"] = sizeof(float); + _typeSize["double"] = sizeof(double); + _typeSize["size_t"] = sizeof(size_t); + + Token * const tok3 = tok2->next(); + const unsigned int sz = sizeOfType(tok3->tokAt(3)); + Token::eraseTokens(tok3, tok3->tokAt(5)); + tok3->insertToken(MathLib::toString(sz)); + } + if (Token::Match(tok2->previous(), "[;{}=]") && !simplifyTemplatesInstantiateMatch(*iter2, name, type.size(), isfunc ? "(" : "*| %var%")) continue; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index e188946fd..ecf51131c 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -114,6 +114,7 @@ private: TEST_CASE(template21); TEST_CASE(template22); TEST_CASE(template23); + TEST_CASE(template24); // #2648 - using sizeof in template parameter TEST_CASE(template_unhandled); TEST_CASE(template_default_parameter); TEST_CASE(template_default_type); @@ -2040,6 +2041,24 @@ private: ASSERT_EQUALS(expected, sizeof_(code)); } + void template24() + { + // #2648 + const char code[] = "template struct B\n" + "{\n" + " int a[n];\n" + "};\n" + "\n" + "template class bitset: B\n" + "{};\n" + "\n" + "bitset<1> z;"; + const char expected[] = "; " + "bitset<1> z ; " + "class bitset<1> : B<4> { } " + "struct B<4> { int a [ 4 ] ; }"; + ASSERT_EQUALS(expected, sizeof_(code)); + } void template_unhandled() { From 7e04ea0859215355ebbaa950aaa449c3b9822358 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 16 Mar 2011 19:54:52 -0400 Subject: [PATCH 5/5] fix removal of throw() from const functions --- lib/tokenize.cpp | 10 ++++++++-- test/testclass.cpp | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index dfeb252f5..b9bdfe11a 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -8558,9 +8558,15 @@ void Tokenizer::removeExceptionSpecifications(Token *tok) const else if (tok->str() == "}") break; - else if (Token::simpleMatch(tok, ") throw (")) + else if (Token::Match(tok, ") const| throw (")) { - Token::eraseTokens(tok, tok->tokAt(2)->link()); + if (tok->next()->str() == "const") + { + Token::eraseTokens(tok->next(), tok->tokAt(3)->link()); + tok = tok->next(); + } + else + Token::eraseTokens(tok, tok->tokAt(2)->link()); tok->deleteNext(); } diff --git a/test/testclass.cpp b/test/testclass.cpp index 7147ebee5..216af4e4e 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -3301,6 +3301,11 @@ private: " { return 0; }\n" "};\n"); ASSERT_EQUALS("", errout.str()); + + checkConst("class Fred {\n" + " const std::string foo() const throw() { return ""; }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); } void const2()