@@ -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
342344static 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
405409void 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
419423CheckUnusedFunctions::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
423430std::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
438447namespace {
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
447458void 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 ())
0 commit comments