Skip to content

Commit 8c1ef55

Browse files
authored
fixed #13762 - added column information for unusedFunction/staticFunction (danmar#7587)
1 parent 7a378f4 commit 8c1ef55

File tree

7 files changed

+82
-66
lines changed

7 files changed

+82
-66
lines changed

lib/checkunusedfunctions.cpp

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,10 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting
105105
usage.usedOtherFile = true;
106106
}
107107

108-
if (!usage.lineNumber)
108+
if (!usage.lineNumber) {
109109
usage.lineNumber = func->token->linenr();
110+
usage.column = func->token->column();
111+
}
110112
usage.isC = func->token->isC();
111113
usage.isStatic = func->isStatic();
112114

@@ -341,13 +343,14 @@ static bool isOperatorFunction(const std::string & funcName)
341343

342344
static void staticFunctionError(ErrorLogger& errorLogger,
343345
const std::string &filename,
344-
unsigned int fileIndex,
345-
unsigned int lineNumber,
346+
nonneg int fileIndex,
347+
nonneg int lineNumber,
348+
nonneg int column,
346349
const std::string &funcname)
347350
{
348351
std::list<ErrorMessage::FileLocation> locationList;
349352
if (!filename.empty()) {
350-
locationList.emplace_back(filename, lineNumber, 0);
353+
locationList.emplace_back(filename, lineNumber, column);
351354
locationList.back().fileIndex = fileIndex;
352355
}
353356

@@ -366,7 +369,8 @@ bool CheckUnusedFunctions::check(const Settings& settings, ErrorLogger& errorLog
366369
{
367370
logChecker("CheckUnusedFunctions::check"); // unusedFunction
368371

369-
using ErrorParams = std::tuple<std::string, unsigned int, unsigned int, std::string>;
372+
// filename, fileindex, line, column
373+
using ErrorParams = std::tuple<std::string, nonneg int, nonneg int, nonneg int, std::string>;
370374
std::vector<ErrorParams> errors; // ensure well-defined order
371375
std::vector<ErrorParams> staticFunctionErrors;
372376

@@ -382,33 +386,33 @@ bool CheckUnusedFunctions::check(const Settings& settings, ErrorLogger& errorLog
382386
std::string filename;
383387
if (func.filename != "+")
384388
filename = func.filename;
385-
errors.emplace_back(filename, func.fileIndex, func.lineNumber, it->first);
389+
errors.emplace_back(filename, func.fileIndex, func.lineNumber, func.column, it->first);
386390
} else if (func.isC && !func.isStatic && !func.usedOtherFile) {
387391
std::string filename;
388392
if (func.filename != "+")
389393
filename = func.filename;
390-
staticFunctionErrors.emplace_back(filename, func.fileIndex, func.lineNumber, it->first);
394+
staticFunctionErrors.emplace_back(filename, func.fileIndex, func.lineNumber, func.column, it->first);
391395
}
392396
}
393397

394398
std::sort(errors.begin(), errors.end());
395399
for (const auto& e : errors)
396-
unusedFunctionError(errorLogger, std::get<0>(e), std::get<1>(e), std::get<2>(e), std::get<3>(e));
400+
unusedFunctionError(errorLogger, std::get<0>(e), std::get<1>(e), std::get<2>(e), std::get<3>(e), std::get<4>(e));
397401

398402
std::sort(staticFunctionErrors.begin(), staticFunctionErrors.end());
399403
for (const auto& e : staticFunctionErrors)
400-
staticFunctionError(errorLogger, std::get<0>(e), std::get<1>(e), std::get<2>(e), std::get<3>(e));
404+
staticFunctionError(errorLogger, std::get<0>(e), std::get<1>(e), std::get<2>(e), std::get<3>(e), std::get<4>(e));
401405

402406
return !errors.empty();
403407
}
404408

405409
void CheckUnusedFunctions::unusedFunctionError(ErrorLogger& errorLogger,
406-
const std::string &filename, unsigned int fileIndex, unsigned int lineNumber,
410+
const std::string &filename, nonneg int fileIndex, nonneg int lineNumber, nonneg int column,
407411
const std::string &funcname)
408412
{
409413
std::list<ErrorMessage::FileLocation> locationList;
410414
if (!filename.empty()) {
411-
locationList.emplace_back(filename, lineNumber, 0);
415+
locationList.emplace_back(filename, lineNumber, column);
412416
locationList.back().fileIndex = fileIndex;
413417
}
414418

@@ -417,7 +421,10 @@ void CheckUnusedFunctions::unusedFunctionError(ErrorLogger& errorLogger,
417421
}
418422

419423
CheckUnusedFunctions::FunctionDecl::FunctionDecl(const Function *f)
420-
: functionName(f->name()), fileIndex(f->token->fileIndex()), lineNumber(f->token->linenr())
424+
: functionName(f->name())
425+
, fileIndex(f->token->fileIndex())
426+
, lineNumber(f->token->linenr())
427+
, column(f->token->column())
421428
{}
422429

423430
std::string CheckUnusedFunctions::analyzerInfo(const Tokenizer &tokenizer) const
@@ -427,7 +434,9 @@ std::string CheckUnusedFunctions::analyzerInfo(const Tokenizer &tokenizer) const
427434
ret << " <functiondecl"
428435
<< " file=\"" << ErrorLogger::toxml(tokenizer.list.getFiles()[functionDecl.fileIndex]) << '\"'
429436
<< " functionName=\"" << ErrorLogger::toxml(functionDecl.functionName) << '\"'
430-
<< " lineNumber=\"" << functionDecl.lineNumber << "\"/>\n";
437+
<< " lineNumber=\"" << functionDecl.lineNumber << '\"'
438+
<< " column=\"" << functionDecl.column << '\"'
439+
<< "/>\n";
431440
}
432441
for (const std::string &fc : mFunctionCalls) {
433442
ret << " <functioncall functionName=\"" << ErrorLogger::toxml(fc) << "\"/>\n";
@@ -437,13 +446,15 @@ std::string CheckUnusedFunctions::analyzerInfo(const Tokenizer &tokenizer) const
437446

438447
namespace {
439448
struct Location {
440-
Location() : lineNumber(0) {}
441-
Location(std::string f, const int l) : fileName(std::move(f)), lineNumber(l) {}
449+
Location() : lineNumber(0), column(0) {}
450+
Location(std::string f, nonneg int l, nonneg int c) : fileName(std::move(f)), lineNumber(l), column(c) {}
442451
std::string fileName;
443-
int lineNumber;
452+
nonneg int lineNumber;
453+
nonneg int column;
444454
};
445455
}
446456

457+
// TODO: bail out on unexpected data
447458
void CheckUnusedFunctions::analyseWholeProgram(const Settings &settings, ErrorLogger &errorLogger, const std::string &buildDir)
448459
{
449460
std::map<std::string, Location> decls;
@@ -490,8 +501,9 @@ void CheckUnusedFunctions::analyseWholeProgram(const Settings &settings, ErrorLo
490501
const char* lineNumber = e2->Attribute("lineNumber");
491502
if (lineNumber) {
492503
const char* file = e2->Attribute("file");
504+
const char* column = default_if_null(e2->Attribute("column"), "0");
493505
// cppcheck-suppress templateInstantiation - TODO: fix this - see #11631
494-
decls[functionName] = Location(file ? file : sourcefile, strToInt<int>(lineNumber));
506+
decls[functionName] = Location(file ? file : sourcefile, strToInt<int>(lineNumber), strToInt<int>(column));
495507
}
496508
}
497509
}
@@ -506,7 +518,7 @@ void CheckUnusedFunctions::analyseWholeProgram(const Settings &settings, ErrorLo
506518

507519
if (calls.find(functionName) == calls.end() && !isOperatorFunction(functionName)) {
508520
const Location &loc = decl->second;
509-
unusedFunctionError(errorLogger, loc.fileName, /*fileIndex*/ 0, loc.lineNumber, functionName);
521+
unusedFunctionError(errorLogger, loc.fileName, /*fileIndex*/ 0, loc.lineNumber, loc.column, functionName);
510522
}
511523
}
512524
}
@@ -516,8 +528,10 @@ void CheckUnusedFunctions::updateFunctionData(const CheckUnusedFunctions& check)
516528
for (const auto& entry : check.mFunctions)
517529
{
518530
FunctionUsage &usage = mFunctions[entry.first];
519-
if (!usage.lineNumber)
531+
if (!usage.lineNumber) {
520532
usage.lineNumber = entry.second.lineNumber;
533+
usage.column = entry.second.column;
534+
}
521535
// TODO: why always overwrite this but not the filename and line?
522536
usage.fileIndex = entry.second.fileIndex;
523537
if (usage.filename.empty())

lib/checkunusedfunctions.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class CPPCHECKLIB CheckUnusedFunctions {
5757
static void analyseWholeProgram(const Settings &settings, ErrorLogger& errorLogger, const std::string &buildDir);
5858

5959
static void getErrorMessages(ErrorLogger &errorLogger) {
60-
unusedFunctionError(errorLogger, "", 0, 0, "funcName");
60+
unusedFunctionError(errorLogger, "", 0, 0, 0, "funcName");
6161
}
6262

6363
// Return true if an error is reported.
@@ -67,13 +67,14 @@ class CPPCHECKLIB CheckUnusedFunctions {
6767

6868
private:
6969
static void unusedFunctionError(ErrorLogger& errorLogger,
70-
const std::string &filename, unsigned int fileIndex, unsigned int lineNumber,
70+
const std::string &filename, nonneg int fileIndex, nonneg int lineNumber, nonneg int column,
7171
const std::string &funcname);
7272

7373
struct CPPCHECKLIB FunctionUsage {
7474
std::string filename;
75-
unsigned int lineNumber{};
76-
unsigned int fileIndex{};
75+
nonneg int lineNumber{};
76+
nonneg int column{};
77+
nonneg int fileIndex{};
7778
bool usedSameFile{};
7879
bool usedOtherFile{};
7980
bool isC{};
@@ -87,7 +88,8 @@ class CPPCHECKLIB CheckUnusedFunctions {
8788
explicit FunctionDecl(const Function *f);
8889
std::string functionName;
8990
nonneg int fileIndex;
90-
unsigned int lineNumber;
91+
nonneg int lineNumber;
92+
nonneg int column;
9193
};
9294
std::list<FunctionDecl> mFunctionDecl;
9395
std::set<std::string> mFunctionCalls;

test/cli/inline-suppress_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def __test_compile_commands_unused_function(tmpdir, use_j):
135135
proj_path_sep = os.path.join(__script_dir, 'proj-inline-suppress-unusedFunction') + os.path.sep
136136
lines = stderr.splitlines()
137137
assert lines == [
138-
"{}B.cpp:6:0: style: The function 'unusedFunctionTest' is never used. [unusedFunction]".format(proj_path_sep)
138+
"{}B.cpp:6:9: style: The function 'unusedFunctionTest' is never used. [unusedFunction]".format(proj_path_sep)
139139
]
140140
assert stdout == ''
141141
assert ret == 1, stdout

test/cli/other_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ class A {
858858
args += extra_args
859859

860860
_, _, stderr = cppcheck(args)
861-
assert stderr == "{}:4:0: style: The function 'f' is never used. [unusedFunction]\n".format(test_h_file)
861+
assert stderr == "{}:4:26: style: The function 'f' is never used. [unusedFunction]\n".format(test_h_file)
862862

863863

864864
def test_unused_function_include(tmpdir):

test/cli/qml_test.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ def __test_unused_functions(extra_args):
2626
lines.sort()
2727
# there are unused functions. But fillSampleData is not unused because that is referenced from main.qml
2828
assert lines == [
29-
"{}samplemodel.cpp:15:0: style: The function 'data' is never used. [unusedFunction]".format(__project_dir_sep),
30-
"{}samplemodel.cpp:38:0: style: The function 'roleNames' is never used. [unusedFunction]".format(__project_dir_sep),
31-
"{}samplemodel.cpp:9:0: style: The function 'rowCount' is never used. [unusedFunction]".format(__project_dir_sep)
29+
"{}samplemodel.cpp:15:23: style: The function 'data' is never used. [unusedFunction]".format(__project_dir_sep),
30+
"{}samplemodel.cpp:38:37: style: The function 'roleNames' is never used. [unusedFunction]".format(__project_dir_sep),
31+
"{}samplemodel.cpp:9:18: style: The function 'rowCount' is never used. [unusedFunction]".format(__project_dir_sep)
3232
]
3333
assert ret == 0, stdout
3434

test/cli/unused_function_test.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def __test_unused_functions(extra_args):
4444
ret, stdout, stderr = cppcheck(args)
4545
assert stdout.splitlines() == []
4646
assert stderr.splitlines() == [
47-
"{}3.c:3:0: style: The function 'f3_3' is never used. [unusedFunction]".format(__project_dir_sep)
47+
"{}3.c:3:6: style: The function 'f3_3' is never used. [unusedFunction]".format(__project_dir_sep)
4848
]
4949
assert ret == 0, stdout
5050

@@ -103,7 +103,7 @@ def __test_unused_functions_project(extra_args):
103103
ret, stdout, stderr = cppcheck(args)
104104
assert stdout.splitlines() == []
105105
assert [
106-
"{}3.c:3:0: style: The function 'f3_3' is never used. [unusedFunction]".format(__project_dir_sep)
106+
"{}3.c:3:6: style: The function 'f3_3' is never used. [unusedFunction]".format(__project_dir_sep)
107107
] == stderr.splitlines()
108108
assert ret == 0, stdout
109109

@@ -163,7 +163,7 @@ def __test_unused_functions_compdb(tmpdir, extra_args):
163163
ret, stdout, stderr = cppcheck(args)
164164
assert stdout.splitlines() == []
165165
assert stderr.splitlines() == [
166-
"{}3.c:3:0: style: The function 'f3_3' is never used. [unusedFunction]".format(__project_dir_sep)
166+
"{}3.c:3:6: style: The function 'f3_3' is never used. [unusedFunction]".format(__project_dir_sep)
167167
]
168168
assert ret == 0, stdout
169169

0 commit comments

Comments
 (0)