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/lib/tokenize.cpp b/lib/tokenize.cpp index 734a5bcdd..b9bdfe11a 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1234,10 +1234,21 @@ 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++; + + 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(); @@ -1256,6 +1267,8 @@ void Tokenizer::simplifyTypedef() } tok = specEnd->next(); } + if (tok->str() == ")") + tok = tok->next(); } else if (Token::Match(tok->tokAt(offset), "( %type% (")) @@ -1519,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 @@ -2955,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; @@ -8517,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(); } @@ -9463,7 +9510,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/testclass.cpp b/test/testclass.cpp index 45a9f22a7..216af4e4e 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 @@ -3300,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() @@ -5791,6 +5797,14 @@ private: ASSERT_EQUALS("", errout.str()); } + void symboldatabase16() + { + // ticket #2637 - segmentation fault + checkConst("{} const const\n"); + + ASSERT_EQUALS("", errout.str()); + } + }; REGISTER_TEST(TestClass) diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 74adc52af..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); @@ -246,6 +247,8 @@ private: TEST_CASE(simplifyTypedef82); // ticket #2403 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 @@ -2038,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() { @@ -4986,6 +5007,34 @@ 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 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() { {