Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions .github/workflows/selfcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ permissions:
contents: read

jobs:
# TODO: enable information
build:

runs-on: ubuntu-22.04
Expand Down Expand Up @@ -77,11 +76,10 @@ jobs:
# make sure the auto-generated GUI dependencies exist
make -C cmake.output gui-build-deps

# TODO: find a way to report unmatched suppressions without need to add information checks
- name: Self check (unusedFunction)
if: false # TODO: fails with preprocessorErrorDirective - see #10667
run: |
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr
env:
DISABLE_VALUEFLOW: 1
UNUSEDFUNCTION_ONLY: 1
Expand All @@ -103,10 +101,9 @@ jobs:
# make sure the auto-generated GUI dependencies exist
make -C cmake.output.notest gui-build-deps

# TODO: find a way to report unmatched suppressions without need to add information checks
- name: Self check (unusedFunction / no test)
run: |
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr
env:
DISABLE_VALUEFLOW: 1
UNUSEDFUNCTION_ONLY: 1
Expand All @@ -122,10 +119,10 @@ jobs:
# make sure the precompiled headers exist
make -C cmake.output.notest_nogui lib/CMakeFiles/cppcheck-core.dir/cmake_pch.hxx.cxx

# TODO: find a way to report unmatched suppressions without need to add information checks
- name: Self check (unusedFunction / no test / no gui)
run: |
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr
supprs="--suppress=unusedFunction:lib/errorlogger.h:193 --suppress=unusedFunction:lib/importproject.cpp:1508 --suppress=unusedFunction:lib/importproject.cpp:1532"
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr $supprs
env:
DISABLE_VALUEFLOW: 1
UNUSEDFUNCTION_ONLY: 1
Expand All @@ -145,11 +142,10 @@ jobs:
# make sure the auto-generated GUI dependencies exist
make -C cmake.output.notest_nocli gui-build-deps

# TODO: find a way to report unmatched suppressions without need to add information checks
- name: Self check (unusedFunction / no test / no cli)
if: false # TODO: the findings are currently too intrusive
run: |
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest_nocli/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nocli/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr
env:
DISABLE_VALUEFLOW: 1
UNUSEDFUNCTION_ONLY: 1
Expand All @@ -165,11 +161,10 @@ jobs:
# make sure the precompiled headers exist
make -C cmake.output.notest_nocli_nogui lib/CMakeFiles/cppcheck-core.dir/cmake_pch.hxx.cxx

# TODO: find a way to report unmatched suppressions without need to add information checks
- name: Self check (unusedFunction / no test / no cli / no gui)
if: false # TODO: the findings are currently too intrusive
run: |
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.notest_nocli_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr
./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib --library=qt -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nocli_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr
env:
DISABLE_VALUEFLOW: 1
UNUSEDFUNCTION_ONLY: 1
Expand All @@ -193,11 +188,10 @@ jobs:
# make sure the auto-generated GUI dependencies exist
make -C cmake.output.corpus gui-build-deps

# TODO: find a way to report unmatched suppressions without need to add information checks
- name: Self check (unusedFunction / corpus / no test / callgrind)
run: |
# TODO: fix -rp so the suppressions actually work
valgrind --tool=callgrind ./cppcheck --template=selfcheck --error-exitcode=0 --library=cppcheck-lib --library=qt -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction --exception-handling -rp=. --project=cmake.output.corpus/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr 2>callgrind.log || (cat callgrind.log && false)
valgrind --tool=callgrind ./cppcheck --template=selfcheck --error-exitcode=0 --library=cppcheck-lib --library=qt -D__GNUC__ -DQT_VERSION=0x060000 -DQ_MOC_OUTPUT_REVISION=69 -DQT_CHARTS_LIB -DQT_MOC_HAS_STRINGDATA --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.corpus/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr 2>callgrind.log || (cat callgrind.log && false)
cat callgrind.log
callgrind_annotate --auto=no > callgrind.annotated.log
head -50 callgrind.annotated.log
Expand Down
6 changes: 3 additions & 3 deletions .selfcheck_unused_suppressions
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# should not be reported - see #13387
checkersReport

# we are not using all methods of their interfaces
unusedFunction:externals/*/*

# usage is disabled
unusedFunction:lib/symboldatabase.cpp

# Q_OBJECT functions which are not called in our code
unusedFunction:cmake.output.notest/gui/cppcheck-gui_autogen/*/moc_aboutdialog.cpp
24 changes: 17 additions & 7 deletions cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include "errorlogger.h"
#include "errortypes.h"
#include "filesettings.h"
#include "json.h"
#include "path.h"
#include "sarifreport.h"
#include "settings.h"
Expand All @@ -49,7 +48,6 @@

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <cstdlib> // EXIT_SUCCESS and EXIT_FAILURE
#include <ctime>
Expand Down Expand Up @@ -339,27 +337,39 @@ bool CppCheckExecutor::reportUnmatchedSuppressions(const Settings &settings, con
assert(!(!files.empty() && !fileSettings.empty()));

// bail out if there is a suppression of unmatchedSuppression which matches any file
const auto suppr = suppressions.getSuppressions();
auto suppr = suppressions.getSuppressions();
if (std::any_of(suppr.cbegin(), suppr.cend(), [](const SuppressionList::Suppression& s) {
return s.errorId == "unmatchedSuppression" && (s.fileName.empty() || s.fileName == "*") && s.lineNumber == SuppressionList::Suppression::NO_LINE;
}))
return false;

SuppressionList supprlist;

const bool doUnusedFunctionOnly = Settings::unusedFunctionOnly();
// ignore all other suppressions if we use the unusedFunction hack
for (auto&& s : suppr)
Comment thread
danmar marked this conversation as resolved.
{
// TODO: checkersReport should not be reported - see #13387
if (doUnusedFunctionOnly && s.errorId != "unusedFunction" && s.errorId != "checkersReport")
continue;
supprlist.addSuppression(std::move(s));
}

bool err = false;

for (auto i = files.cbegin(); i != files.cend(); ++i) {
err |= ::reportUnmatchedSuppressions(suppressions.getUnmatchedLocalSuppressions(*i), errorLogger, settings.unmatchedSuppressionFilters);
err |= ::reportUnmatchedSuppressions(supprlist.getUnmatchedLocalSuppressions(*i), errorLogger, settings.unmatchedSuppressionFilters);
}

for (auto i = fileSettings.cbegin(); i != fileSettings.cend(); ++i) {
err |= ::reportUnmatchedSuppressions(suppressions.getUnmatchedLocalSuppressions(i->file), errorLogger, settings.unmatchedSuppressionFilters);
err |= ::reportUnmatchedSuppressions(supprlist.getUnmatchedLocalSuppressions(i->file), errorLogger, settings.unmatchedSuppressionFilters);
}

if (settings.inlineSuppressions) {
err |= ::reportUnmatchedSuppressions(suppressions.getUnmatchedInlineSuppressions(), errorLogger, settings.unmatchedSuppressionFilters);
err |= ::reportUnmatchedSuppressions(supprlist.getUnmatchedInlineSuppressions(), errorLogger, settings.unmatchedSuppressionFilters);
}

err |= ::reportUnmatchedSuppressions(suppressions.getUnmatchedGlobalSuppressions(), errorLogger, settings.unmatchedSuppressionFilters);
err |= ::reportUnmatchedSuppressions(supprlist.getUnmatchedGlobalSuppressions(), errorLogger, settings.unmatchedSuppressionFilters);
return err;
}

Expand Down
1 change: 0 additions & 1 deletion gui/checkthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ void CheckThread::analyseWholeProgram(const std::list<FileWithDetails> &files, c
start();
}

// cppcheck-suppress unusedFunction - TODO: false positive
void CheckThread::run()
{
mState = Running;
Expand Down
22 changes: 20 additions & 2 deletions gui/projectfiledialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,24 @@ static const std::array<Platform::Type, 6> builtinPlatforms = {
Platform::Type::Unix64
};

static std::string suppressionAsText(const SuppressionList::Suppression& s)
{
std::string ret;
if (!s.errorId.empty())
ret = s.errorId;
if (!s.fileName.empty())
ret += " fileName=" + s.fileName;
if (s.lineNumber != SuppressionList::Suppression::NO_LINE)
ret += " lineNumber=" + std::to_string(s.lineNumber);
if (!s.symbolName.empty())
ret += " symbolName=" + s.symbolName;
if (s.hash > 0)
ret += " hash=" + std::to_string(s.hash);
if (startsWith(ret," "))
return ret.substr(1);
return ret;
}

QStringList ProjectFileDialog::getProjectConfigs(const QString &fileName)
{
if (!fileName.endsWith(".sln") && !fileName.endsWith(".vcxproj"))
Expand Down Expand Up @@ -808,7 +826,7 @@ void ProjectFileDialog::setLibraries(const QStringList &libraries)
void ProjectFileDialog::addSingleSuppression(const SuppressionList::Suppression &suppression)
{
mSuppressions += suppression;
mUI->mListSuppressions->addItem(QString::fromStdString(suppression.getText()));
mUI->mListSuppressions->addItem(QString::fromStdString(suppressionAsText(suppression)));
Comment thread
danmar marked this conversation as resolved.
}

void ProjectFileDialog::setSuppressions(const QList<SuppressionList::Suppression> &suppressions)
Expand Down Expand Up @@ -949,7 +967,7 @@ int ProjectFileDialog::getSuppressionIndex(const QString &shortText) const
{
const std::string s = shortText.toStdString();
auto it = std::find_if(mSuppressions.cbegin(), mSuppressions.cend(), [&](const SuppressionList::Suppression& sup) {
return sup.getText() == s;
return suppressionAsText(sup) == s;
});
return it == mSuppressions.cend() ? -1 : static_cast<int>(std::distance(mSuppressions.cbegin(), it));
}
Expand Down
3 changes: 1 addition & 2 deletions lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1340,8 +1340,7 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer, AnalyzerInformation

// TODO: this should actually be the behavior if only "--enable=unusedFunction" is specified - see #10648
// TODO: log message when this is active?
const char* unusedFunctionOnly = std::getenv("UNUSEDFUNCTION_ONLY");
const bool doUnusedFunctionOnly = unusedFunctionOnly && (std::strcmp(unusedFunctionOnly, "1") == 0);
const bool doUnusedFunctionOnly = Settings::unusedFunctionOnly();

if (!doUnusedFunctionOnly) {
const std::time_t maxTime = mSettings.checksMaxTime > 0 ? std::time(nullptr) + mSettings.checksMaxTime : 0;
Expand Down
1 change: 0 additions & 1 deletion lib/errorlogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ class CPPCHECKLIB ErrorMessage {
}

/** Verbose message (may be the same as the short message) */
// cppcheck-suppress unusedFunction - used by GUI only
const std::string &verboseMessage() const {
return mVerboseMessage;
}
Expand Down
2 changes: 0 additions & 2 deletions lib/importproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,6 @@ void ImportProject::selectOneVsConfig(Platform::Type platform)
}
}

// cppcheck-suppress unusedFunction - used by GUI only
void ImportProject::selectVsConfigurations(Platform::Type platform, const std::vector<std::string> &configurations)
{
for (auto it = fileSettings.cbegin(); it != fileSettings.cend();) {
Expand All @@ -1530,7 +1529,6 @@ void ImportProject::selectVsConfigurations(Platform::Type platform, const std::v
}
}

// cppcheck-suppress unusedFunction - used by GUI only
std::list<std::string> ImportProject::getVSConfigs()
{
return std::list<std::string>(mAllVSConfigs.cbegin(), mAllVSConfigs.cend());
Expand Down
3 changes: 0 additions & 3 deletions lib/keywords.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ static const std::unordered_set<std::string> cpp26_keywords_all = {
CPP03_KEYWORDS, CPP11_KEYWORDS, CPP20_KEYWORDS
};

// cppcheck-suppress unusedFunction
const std::unordered_set<std::string>& Keywords::getAll(Standards::cstd_t cStd)
{
switch (cStd) {
Expand All @@ -193,7 +192,6 @@ const std::unordered_set<std::string>& Keywords::getAll(Standards::cstd_t cStd)
cppcheck::unreachable();
}

// cppcheck-suppress unusedFunction
const std::unordered_set<std::string>& Keywords::getAll(Standards::cppstd_t cppStd) {
switch (cppStd) {
case Standards::cppstd_t::CPP03:
Expand Down Expand Up @@ -234,7 +232,6 @@ const std::unordered_set<std::string>& Keywords::getOnly(Standards::cstd_t cStd)
cppcheck::unreachable();
}

// cppcheck-suppress unusedFunction
const std::unordered_set<std::string>& Keywords::getOnly(Standards::cppstd_t cppStd)
{
switch (cppStd) {
Expand Down
1 change: 0 additions & 1 deletion lib/mathlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,6 @@ static bool isValidIntegerSuffixIt(std::string::const_iterator it, std::string::
(state == Status::SUFFIX_LITERAL));
}

// cppcheck-suppress unusedFunction
bool MathLib::isValidIntegerSuffix(const std::string& str, bool supportMicrosoftExtensions)
{
return isValidIntegerSuffixIt(str.cbegin(), str.cend(), supportMicrosoftExtensions);
Expand Down
1 change: 0 additions & 1 deletion lib/programmemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ const ValueFlow::Value* ProgramMemory::getValue(nonneg int exprid, bool impossib
return nullptr;
}

// cppcheck-suppress unusedFunction
bool ProgramMemory::getIntValue(nonneg int exprid, MathLib::bigint& result) const
{
const ValueFlow::Value* value = getValue(exprid);
Expand Down
8 changes: 8 additions & 0 deletions lib/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "vfvalue.h"

#include <cctype>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
Expand Down Expand Up @@ -715,3 +717,9 @@ Settings::ExecutorType Settings::defaultExecutor()
#endif
return defaultExecutor;
}

bool Settings::unusedFunctionOnly()
{
const char* unusedFunctionOnly = std::getenv("UNUSEDFUNCTION_ONLY");
return unusedFunctionOnly && (std::strcmp(unusedFunctionOnly, "1") == 0);
}
3 changes: 2 additions & 1 deletion lib/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -554,9 +554,10 @@ class CPPCHECKLIB WARN_UNUSED Settings {

void setCheckLevel(CheckLevel level);


static ExecutorType defaultExecutor();

static bool unusedFunctionOnly();

private:
static std::string parseEnabled(const std::string &str, std::tuple<SimpleEnableGroup<Severity>, SimpleEnableGroup<Checks>> &groups);
std::string applyEnabled(const std::string &str, bool enable);
Expand Down
21 changes: 0 additions & 21 deletions lib/suppressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include "suppressions.h"

#include "errorlogger.h"
#include "errortypes.h"
#include "filesettings.h"
#include "path.h"
#include "pathmatch.h"
Expand Down Expand Up @@ -302,7 +301,6 @@ std::string SuppressionList::addSuppressions(std::list<Suppression> suppressions
return "";
}

// cppcheck-suppress unusedFunction
bool SuppressionList::updateSuppressionState(const SuppressionList::Suppression& suppression)
{
std::lock_guard<std::mutex> lg(mSuppressionsSync);
Expand Down Expand Up @@ -446,25 +444,6 @@ bool SuppressionList::Suppression::isMatch(const SuppressionList::ErrorMessage &
cppcheck::unreachable();
}

// cppcheck-suppress unusedFunction - used by GUI only
std::string SuppressionList::Suppression::getText() const
{
std::string ret;
if (!errorId.empty())
ret = errorId;
if (!fileName.empty())
ret += " fileName=" + fileName;
if (lineNumber != NO_LINE)
ret += " lineNumber=" + std::to_string(lineNumber);
if (!symbolName.empty())
ret += " symbolName=" + symbolName;
if (hash > 0)
ret += " hash=" + std::to_string(hash);
if (startsWith(ret," "))
return ret.substr(1);
return ret;
}

bool SuppressionList::isSuppressed(const SuppressionList::ErrorMessage &errmsg, bool global)
{
std::lock_guard<std::mutex> lg(mSuppressionsSync);
Expand Down
2 changes: 0 additions & 2 deletions lib/suppressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ class CPPCHECKLIB SuppressionList {

bool isMatch(const ErrorMessage &errmsg);

std::string getText() const;

bool isWildcard() const {
return fileName.find_first_of("?*") != std::string::npos;
}
Expand Down
1 change: 1 addition & 0 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6404,6 +6404,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const

//---------------------------------------------------------------------------

// cppcheck-suppress unusedFunction
const Scope *SymbolDatabase::findScopeByName(const std::string& name) const
{
auto it = std::find_if(scopeList.cbegin(), scopeList.cend(), [&](const Scope& s) {
Expand Down
1 change: 0 additions & 1 deletion lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2630,7 +2630,6 @@ const ValueFlow::Value* Token::getMovedValue() const
return it == mImpl->mValues->end() ? nullptr : &*it;
}

// cppcheck-suppress unusedFunction
const ValueFlow::Value* Token::getContainerSizeValue(const MathLib::bigint val) const
{
if (!mImpl->mValues)
Expand Down
1 change: 0 additions & 1 deletion lib/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,6 @@ T strToInt(const std::string& str)
* \return size of array
* */
template<typename T, int size>
// cppcheck-suppress unusedFunction - only used in conditional code
std::size_t getArrayLength(const T (& /*unused*/)[size])
{
return size;
Expand Down