diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp index f538b3a3544..3fc19d340d7 100644 --- a/lib/checkunusedfunctions.cpp +++ b/lib/checkunusedfunctions.cpp @@ -59,6 +59,11 @@ static std::string stripTemplateParameters(const std::string& funcName) { // FUNCTION USAGE - Check for unused functions etc //--------------------------------------------------------------------------- +static bool isRecursiveCall(const Token* ftok) +{ + return ftok->function() && ftok->function() == Scope::nestedInFunction(ftok->scope()); +} + void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Settings &settings) { const char * const FileName = tokenizer.list.getFiles().front().c_str(); @@ -245,6 +250,8 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting } if (funcname) { + if (isRecursiveCall(funcname)) + continue; const auto baseName = stripTemplateParameters(funcname->str()); FunctionUsage &func = mFunctions[baseName]; const std::string& called_from_file = tokenizer.list.getFiles()[funcname->fileIndex()]; diff --git a/lib/clangimport.cpp b/lib/clangimport.cpp index 430771cdea2..984b297a8b0 100644 --- a/lib/clangimport.cpp +++ b/lib/clangimport.cpp @@ -330,7 +330,7 @@ namespace clangimport { void dumpAst(int num = 0, int indent = 0) const; void createTokens1(TokenList &tokenList) { - //dumpAst(); + //dumpAst(); // TODO: reactivate or remove if (!tokenList.back()) { setLocations(tokenList, 0, 1, 1); // FIXME: treat as C++ if no filename (i.e. no lang) is specified for now @@ -486,6 +486,7 @@ std::string clangimport::AstNode::getTemplateParameters() const return templateParameters + ">"; } +// cppcheck-suppress unusedFunction // only used in comment void clangimport::AstNode::dumpAst(int num, int indent) const { (void)num; diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 242d6ef2cef..e2d618d1061 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -1274,44 +1274,6 @@ bool MathLib::isOctalDigit(char c) return (c >= '0' && c <= '7'); } -bool MathLib::isDigitSeparator(const std::string& iCode, std::string::size_type iPos) -{ - if (iPos == 0 || iPos >= iCode.size() || iCode[iPos] != '\'') - return false; - std::string::size_type i = iPos - 1; - while (std::isxdigit(iCode[i])) { - if (i == 0) - return true; // Only xdigits before ' - --i; - } - if (i == iPos - 1) // No xdigit before ' - return false; - - switch (iCode[i]) { - case ' ': - case '.': - case ',': - case 'x': - case '(': - case '{': - case '+': - case '-': - case '*': - case '%': - case '/': - case '&': - case '|': - case '^': - case '~': - case '=': - return true; - case '\'': - return isDigitSeparator(iCode, i); - default: - return false; - } -} - MathLib::value operator+(const MathLib::value &v1, const MathLib::value &v2) { return MathLib::value::calc('+',v1,v2); diff --git a/lib/mathlib.h b/lib/mathlib.h index 5a3ec0c5f69..9075cdcc811 100644 --- a/lib/mathlib.h +++ b/lib/mathlib.h @@ -126,13 +126,6 @@ class CPPCHECKLIB MathLib { static bool isOctalDigit(char c); static unsigned int encodeMultiChar(const std::string& str); - - /** - * \param[in] iCode Code being considered - * \param[in] iPos A posision within iCode - * \return Whether iCode[iPos] is a C++14 digit separator - */ - static bool isDigitSeparator(const std::string& iCode, std::string::size_type iPos); }; MathLib::value operator+(const MathLib::value &v1, const MathLib::value &v2); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 1ee239a9e74..b21ba232633 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1152,7 +1152,7 @@ void SymbolDatabase::createSymbolDatabaseSetFunctionPointers(bool firstPass) inTemplateArg = tok->link(); if (inTemplateArg == tok) inTemplateArg = nullptr; - if (tok->isName() && !tok->function() && tok->varId() == 0 && ((tok->astParent() && tok->astParent()->isComparisonOp()) || Token::Match(tok, "%name% [{(,)>;]]")) && !isReservedName(tok)) { + if (tok->isName() && !tok->function() && tok->varId() == 0 && ((tok->astParent() && tok->astParent()->isComparisonOp()) || Token::Match(tok, "%name% [{(,)>;:]]")) && !isReservedName(tok)) { if (tok->strAt(1) == ">" && !tok->linkAt(1)) continue; diff --git a/lib/token.cpp b/lib/token.cpp index e7e925f421b..aee3150bd19 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1702,6 +1702,7 @@ std::string Token::astStringVerbose() const return ret; } +// cppcheck-suppress unusedFunction // used in test std::string Token::astStringZ3() const { if (!astOperand1()) diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 1c7e631bb1d..3c441b8da2b 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -60,7 +60,6 @@ class TestMathLib : public TestFixture { TEST_CASE(tan); TEST_CASE(abs); TEST_CASE(toString); - TEST_CASE(CPP14DigitSeparators); } void isGreater() const { @@ -1475,24 +1474,6 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS("2.22507385851e-308", MathLib::toString(std::numeric_limits::min())); ASSERT_EQUALS("1.79769313486e+308", MathLib::toString(std::numeric_limits::max())); } - - void CPP14DigitSeparators() const { // Ticket #7137, #7565 - ASSERT(MathLib::isDigitSeparator("'", 0) == false); - ASSERT(MathLib::isDigitSeparator("123'0;", 3)); - ASSERT(MathLib::isDigitSeparator("foo(1'2);", 5)); - ASSERT(MathLib::isDigitSeparator("foo(1,1'2);", 7)); - ASSERT(MathLib::isDigitSeparator("int a=1'234-1'2-'0';", 7)); - ASSERT(MathLib::isDigitSeparator("int a=1'234-1'2-'0';", 13)); - ASSERT(MathLib::isDigitSeparator("int a=1'234-1'2-'0';", 16) == false); - ASSERT(MathLib::isDigitSeparator("int b=1+9'8;", 9)); - ASSERT(MathLib::isDigitSeparator("if (1'2) { char c = 'c'; }", 5)); - ASSERT(MathLib::isDigitSeparator("if (120%1'2) { char c = 'c'; }", 9)); - ASSERT(MathLib::isDigitSeparator("if (120&1'2) { char c = 'c'; }", 9)); - ASSERT(MathLib::isDigitSeparator("if (120|1'2) { char c = 'c'; }", 9)); - ASSERT(MathLib::isDigitSeparator("if (120%1'2) { char c = 'c'; }", 24) == false); - ASSERT(MathLib::isDigitSeparator("if (120%1'2) { char c = 'c'; }", 26) == false); - ASSERT(MathLib::isDigitSeparator("0b0000001'0010'01110", 14)); - } }; REGISTER_TEST(TestMathLib) diff --git a/test/testunusedfunctions.cpp b/test/testunusedfunctions.cpp index 91f1c1e11bf..2b1773f2f66 100644 --- a/test/testunusedfunctions.cpp +++ b/test/testunusedfunctions.cpp @@ -67,6 +67,7 @@ class TestUnusedFunctions : public TestFixture { TEST_CASE(member_function_ternary); TEST_CASE(boost); TEST_CASE(enumValues); + TEST_CASE(recursive); TEST_CASE(multipleFiles); // same function name in multiple files @@ -116,7 +117,7 @@ class TestUnusedFunctions : public TestFixture { " if (f1())\n" " { }\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:1]: (style) The function 'f1' is never used.\n", errout_str()); } void return1() { @@ -124,15 +125,15 @@ class TestUnusedFunctions : public TestFixture { "{\n" " return f1();\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:1]: (style) The function 'f1' is never used.\n", errout_str()); } void return2() { check("char * foo()\n" "{\n" - " return *foo();\n" + " return foo();\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:1]: (style) The function 'foo' is never used.\n", errout_str()); } void return3() { @@ -158,7 +159,7 @@ class TestUnusedFunctions : public TestFixture { "{\n" " void (*f)() = cond ? f1 : NULL;\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:1]: (style) The function 'f1' is never used.\n", errout_str()); } void callback2() { // #8677 @@ -180,7 +181,7 @@ class TestUnusedFunctions : public TestFixture { " if (cond) ;\n" " else f1();\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:1]: (style) The function 'f1' is never used.\n", errout_str()); } void functionpointer() { @@ -255,7 +256,7 @@ class TestUnusedFunctions : public TestFixture { "}\n" "\n" "void h() { g(); h(); }"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:8]: (style) The function 'h' is never used.\n", errout_str()); } void template3() { // #4701 @@ -286,7 +287,7 @@ class TestUnusedFunctions : public TestFixture { " test();\n" " }\n" "};"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:11]: (style) The function 'test' is never used.\n", errout_str()); } void template5() { // #9220 @@ -322,7 +323,7 @@ class TestUnusedFunctions : public TestFixture { "};\n"); ASSERT_EQUALS("[test.cpp:3]: (style) The function 'tf' is never used.\n", errout_str()); - check("struct S {\n" + check("struct C {\n" " template\n" " void tf(const T&) { }\n" "};\n" @@ -332,7 +333,7 @@ class TestUnusedFunctions : public TestFixture { "}\n"); ASSERT_EQUALS("", errout_str()); - check("struct S {\n" + check("struct C {\n" " template\n" " void tf(const T&) { }\n" "};\n" @@ -523,10 +524,11 @@ class TestUnusedFunctions : public TestFixture { } void boost() { - check("static void _xy(const char *b, const char *e)\n" - "{}\n" - "parse(line, blanks_p >> ident[&_xy] >> blanks_p >> eol_p).full"); - ASSERT_EQUALS("", errout_str()); + check("static void _xy(const char *b, const char *e) {}\n" + "void f() {\n" + " parse(line, blanks_p >> ident[&_xy] >> blanks_p >> eol_p).full;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) The function 'f' is never used.\n", errout_str()); } void enumValues() { // #11486 @@ -541,6 +543,14 @@ class TestUnusedFunctions : public TestFixture { errout_str()); } + void recursive() { + check("void f() {\n" // #8159 + " f();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:1]: (style) The function 'f' is never used.\n", + errout_str()); + } + void multipleFiles() { CheckUnusedFunctions c; @@ -576,7 +586,7 @@ class TestUnusedFunctions : public TestFixture { ASSERT_EQUALS("[test.cpp:2]: (style) The function 'f' is never used.\n", errout_str()); check("void f(void) {}\n" - "void (*list[])(void) = {f}"); + "void (*list[])(void) = {f};"); ASSERT_EQUALS("", errout_str()); }