Fix #11486 FN unusedFunction when enum value with same name exists (#4690)

This commit is contained in:
chrchr-github 2023-01-08 14:30:42 +01:00 committed by GitHub
parent cefc105c5f
commit 911d610f2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 7 deletions

View File

@ -214,7 +214,7 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const char Fi
funcname = tok->next(); funcname = tok->next();
while (Token::Match(funcname, "%name% :: %name%")) while (Token::Match(funcname, "%name% :: %name%"))
funcname = funcname->tokAt(2); funcname = funcname->tokAt(2);
} else if (Token::Match(tok, "[;{}.,()[=+-/|!?:]")) { } else if (tok->scope()->type != Scope::ScopeType::eEnum && Token::Match(tok, "[;{}.,()[=+-/|!?:]")) {
funcname = tok->next(); funcname = tok->next();
if (funcname && funcname->str() == "&") if (funcname && funcname->str() == "&")
funcname = funcname->next(); funcname = funcname->next();
@ -305,14 +305,15 @@ static bool isOperatorFunction(const std::string & funcName)
bool CheckUnusedFunctions::check(ErrorLogger * const errorLogger, const Settings& settings) const bool CheckUnusedFunctions::check(ErrorLogger * const errorLogger, const Settings& settings) const
{ {
bool errors = false; using ErrorParams = std::tuple<std::string, unsigned int, std::string>;
std::vector<ErrorParams> errors; // ensure well-defined order
for (std::unordered_map<std::string, FunctionUsage>::const_iterator it = mFunctions.cbegin(); it != mFunctions.cend(); ++it) { for (std::unordered_map<std::string, FunctionUsage>::const_iterator it = mFunctions.cbegin(); it != mFunctions.cend(); ++it) {
const FunctionUsage &func = it->second; const FunctionUsage &func = it->second;
if (func.usedOtherFile || func.filename.empty()) if (func.usedOtherFile || func.filename.empty())
continue; continue;
if (it->first == "main" || if (it->first == "main" ||
(settings.isWindowsPlatform() && (it->first == "WinMain" || it->first == "_tmain")) || (settings.isWindowsPlatform() && (it->first == "WinMain" || it->first == "_tmain")))
it->first == "if")
continue; continue;
if (!func.usedSameFile) { if (!func.usedSameFile) {
if (isOperatorFunction(it->first)) if (isOperatorFunction(it->first))
@ -320,8 +321,7 @@ bool CheckUnusedFunctions::check(ErrorLogger * const errorLogger, const Settings
std::string filename; std::string filename;
if (func.filename != "+") if (func.filename != "+")
filename = func.filename; filename = func.filename;
unusedFunctionError(errorLogger, filename, func.lineNumber, it->first); errors.emplace_back(filename, func.lineNumber, it->first);
errors = true;
} else if (!func.usedOtherFile) { } else if (!func.usedOtherFile) {
/** @todo add error message "function is only used in <file> it can be static" */ /** @todo add error message "function is only used in <file> it can be static" */
/* /*
@ -332,7 +332,10 @@ bool CheckUnusedFunctions::check(ErrorLogger * const errorLogger, const Settings
*/ */
} }
} }
return errors; std::sort(errors.begin(), errors.end());
for (const auto& e : errors)
unusedFunctionError(errorLogger, std::get<0>(e), std::get<1>(e), std::get<2>(e));
return !errors.empty();
} }
void CheckUnusedFunctions::unusedFunctionError(ErrorLogger * const errorLogger, void CheckUnusedFunctions::unusedFunctionError(ErrorLogger * const errorLogger,

View File

@ -61,6 +61,7 @@ private:
TEST_CASE(initializer_list); TEST_CASE(initializer_list);
TEST_CASE(member_function_ternary); TEST_CASE(member_function_ternary);
TEST_CASE(boost); TEST_CASE(boost);
TEST_CASE(enumValues);
TEST_CASE(multipleFiles); // same function name in multiple files TEST_CASE(multipleFiles); // same function name in multiple files
@ -442,6 +443,18 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void enumValues() { // #11486
check("enum E1 { Break1 };\n"
"struct S {\n"
" enum class E { Break };\n"
" void Break() {}\n"
" void Break1() {}\n"
"};\n");
ASSERT_EQUALS("[test.cpp:4]: (style) The function 'Break' is never used.\n"
"[test.cpp:5]: (style) The function 'Break1' is never used.\n",
errout.str());
}
void multipleFiles() { void multipleFiles() {
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);
CheckUnusedFunctions c(&tokenizer, &settings, nullptr); CheckUnusedFunctions c(&tokenizer, &settings, nullptr);