Fix #9567 (Inline suppression of unusedFunction errors not working when using compile database) (#2870)
This commit is contained in:
parent
05b804d126
commit
f70e8de315
|
@ -420,7 +420,9 @@ unsigned int CppCheck::check(const ImportProject::FileSettings &fs)
|
|||
temp.check(Path::simplifyPath(fs.filename));
|
||||
}
|
||||
std::ifstream fin(fs.filename);
|
||||
return temp.checkFile(Path::simplifyPath(fs.filename), fs.cfg, fin);
|
||||
unsigned int returnValue = temp.checkFile(Path::simplifyPath(fs.filename), fs.cfg, fin);
|
||||
mSettings.nomsg.addSuppressions(temp.mSettings.nomsg.getSuppressions());
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
unsigned int CppCheck::checkFile(const std::string& filename, const std::string &cfgname, std::istream& fileStream)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cctype> // std::isdigit, std::isalnum, etc
|
||||
#include <functional> // std::bind, std::placeholders
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
|
@ -217,6 +218,16 @@ std::string Suppressions::addSuppressionLine(const std::string &line)
|
|||
|
||||
std::string Suppressions::addSuppression(const Suppressions::Suppression &suppression)
|
||||
{
|
||||
// Check if suppression is already in list
|
||||
auto foundSuppression = std::find_if(mSuppressions.begin(), mSuppressions.end(),
|
||||
std::bind(&Suppression::isSameParameters, &suppression, std::placeholders::_1));
|
||||
if (foundSuppression != mSuppressions.end()) {
|
||||
// Update matched state of existing global suppression
|
||||
if (!suppression.isLocal() && suppression.matched)
|
||||
foundSuppression->matched = suppression.matched;
|
||||
return "";
|
||||
}
|
||||
|
||||
// Check that errorId is valid..
|
||||
if (suppression.errorId.empty() && suppression.hash == 0)
|
||||
return "Failed to add suppression. No id.";
|
||||
|
@ -242,6 +253,16 @@ std::string Suppressions::addSuppression(const Suppressions::Suppression &suppre
|
|||
return "";
|
||||
}
|
||||
|
||||
std::string Suppressions::addSuppressions(const std::list<Suppression> &suppressions)
|
||||
{
|
||||
for (const auto &newSuppression : suppressions) {
|
||||
auto errmsg = addSuppression(newSuppression);
|
||||
if (errmsg != "")
|
||||
return errmsg;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void Suppressions::ErrorMessage::setFileName(const std::string &s)
|
||||
{
|
||||
mFileName = Path::simplifyPath(s);
|
||||
|
@ -419,3 +440,8 @@ std::list<Suppressions::Suppression> Suppressions::getUnmatchedGlobalSuppression
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::list<Suppressions::Suppression> Suppressions::getSuppressions() const
|
||||
{
|
||||
return mSuppressions;
|
||||
}
|
||||
|
|
|
@ -93,12 +93,22 @@ public:
|
|||
bool isSuppressed(const ErrorMessage &errmsg) const;
|
||||
|
||||
bool isMatch(const ErrorMessage &errmsg);
|
||||
|
||||
std::string getText() const;
|
||||
|
||||
bool isLocal() const {
|
||||
return !fileName.empty() && fileName.find_first_of("?*") == std::string::npos;
|
||||
}
|
||||
|
||||
bool isSameParameters(const Suppression &other) const {
|
||||
return errorId == other.errorId &&
|
||||
fileName == other.fileName &&
|
||||
lineNumber == other.lineNumber &&
|
||||
symbolName == other.symbolName &&
|
||||
hash == other.hash &&
|
||||
thisAndNextLine == other.thisAndNextLine;
|
||||
}
|
||||
|
||||
std::string errorId;
|
||||
std::string fileName;
|
||||
int lineNumber;
|
||||
|
@ -147,6 +157,13 @@ public:
|
|||
*/
|
||||
std::string addSuppression(const Suppression &suppression);
|
||||
|
||||
/**
|
||||
* @brief Combine list of suppressions into the current suppressions.
|
||||
* @param suppressions list of suppression details
|
||||
* @return error message. empty upon success
|
||||
*/
|
||||
std::string addSuppressions(const std::list<Suppression> &suppressions);
|
||||
|
||||
/**
|
||||
* @brief Returns true if this message should not be shown to the user.
|
||||
* @param errmsg error message
|
||||
|
@ -179,6 +196,12 @@ public:
|
|||
*/
|
||||
std::list<Suppression> getUnmatchedGlobalSuppressions(const bool unusedFunctionChecking) const;
|
||||
|
||||
/**
|
||||
* @brief Returns list of all suppressions.
|
||||
* @return list of suppressions
|
||||
*/
|
||||
std::list<Suppression> getSuppressions() const;
|
||||
|
||||
private:
|
||||
/** @brief List of error which the user doesn't want to see. */
|
||||
std::list<Suppression> mSuppressions;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#include "B.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
B b();
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#include "B.hpp"
|
||||
|
||||
B::B() {}
|
||||
|
||||
// cppcheck-suppress unusedFunction
|
||||
void B::unusedFunctionTest() {}
|
|
@ -0,0 +1,6 @@
|
|||
class B {
|
||||
public:
|
||||
B();
|
||||
|
||||
void unusedFunctionTest();
|
||||
};
|
|
@ -1,10 +1,23 @@
|
|||
|
||||
# python -m pytest test-inline-suppress.py
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from testutils import cppcheck
|
||||
|
||||
def create_unused_function_compile_commands():
|
||||
compile_commands = os.path.join('proj-inline-suppress-unusedFunction', 'compile_commands.json')
|
||||
prjpath = os.path.join(os.getcwd(), 'proj-inline-suppress-unusedFunction')
|
||||
j = [{'directory': prjpath,
|
||||
'command': '/usr/bin/c++ -I"' + prjpath + '" -o "' + os.path.join(prjpath, 'B.cpp.o') + '" -c "' + os.path.join(prjpath, 'B.cpp') + '"',
|
||||
'file': os.path.join(prjpath, 'B.cpp')},
|
||||
{'directory': prjpath,
|
||||
'command': '/usr/bin/c++ -I"' + prjpath + '" -o "' + os.path.join(prjpath, 'A.cpp.o') + '" -c "' + os.path.join(prjpath, 'A.cpp') + '"',
|
||||
'file': os.path.join(prjpath, 'A.cpp')}]
|
||||
with open(compile_commands, 'wt') as f:
|
||||
f.write(json.dumps(j, indent=4))
|
||||
|
||||
def test1():
|
||||
ret, stdout, stderr = cppcheck(['--inline-suppr', 'proj-inline-suppress'])
|
||||
assert ret == 0
|
||||
|
@ -31,3 +44,15 @@ def test_backwards_compatibility():
|
|||
|
||||
ret, stdout, stderr = cppcheck(['--inline-suppr', 'proj-inline-suppress/3.cpp'])
|
||||
assert stderr == ''
|
||||
|
||||
def test_compile_commands_unused_function():
|
||||
create_unused_function_compile_commands()
|
||||
ret, stdout, stderr = cppcheck(['--enable=all', '--error-exitcode=1', '--project=./proj-inline-suppress-unusedFunction/compile_commands.json'])
|
||||
assert ret == 1
|
||||
assert 'unusedFunction' in stderr
|
||||
|
||||
def test_compile_commands_unused_function_suppression():
|
||||
create_unused_function_compile_commands()
|
||||
ret, stdout, stderr = cppcheck(['--enable=all', '--inline-suppr', '--error-exitcode=1', '--project=./proj-inline-suppress-unusedFunction/compile_commands.json'])
|
||||
assert ret == 0
|
||||
assert 'unusedFunction' not in stderr
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
# Create Cppcheck project file
|
||||
|
@ -47,6 +48,14 @@ def cppcheck(args):
|
|||
exe = '../../cppcheck.exe'
|
||||
elif os.path.isfile('../../../cppcheck.exe'):
|
||||
exe = '../../../cppcheck.exe'
|
||||
elif os.path.isfile('../../bin/cppcheck.exe'):
|
||||
exe = '../../bin/cppcheck.exe'
|
||||
elif os.path.isfile('../../../bin/cppcheck.exe'):
|
||||
exe = '../../../bin/cppcheck.exe'
|
||||
elif os.path.isfile('../../bin/cppcheck'):
|
||||
exe = '../../bin/cppcheck'
|
||||
elif os.path.isfile('../../../bin/cppcheck'):
|
||||
exe = '../../../bin/cppcheck'
|
||||
elif os.path.isfile('../../cppcheck'):
|
||||
exe = '../../cppcheck'
|
||||
else:
|
||||
|
@ -58,4 +67,3 @@ def cppcheck(args):
|
|||
stdout = comm[0].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n')
|
||||
stderr = comm[1].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n')
|
||||
return p.returncode, stdout, stderr
|
||||
|
||||
|
|
Loading…
Reference in New Issue