Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/selfcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ jobs:
- name: Self check (unusedFunction / no test / no gui)
run: |
supprs="--suppress=unusedFunction:lib/errorlogger.h:196 --suppress=unusedFunction:lib/importproject.cpp:1531 --suppress=unusedFunction:lib/importproject.cpp:1555"
supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1531 --suppress=unusedFunction:lib/importproject.cpp:1555"
./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
Expand Down
4 changes: 4 additions & 0 deletions lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,8 @@ void CppCheck::internalError(const std::string &filename, const std::string &msg

void CppCheck::checkNormalTokens(const Tokenizer &tokenizer, AnalyzerInformation* analyzerInformation, const std::string& currentConfig)
{
const ProgressReporter progressReporter(mErrorLogger, mSettings.reportProgress, tokenizer.list.getSourceFilePath(), "Run checkers");

CheckUnusedFunctions unusedFunctionsChecker;

// TODO: this should actually be the behavior if only "--enable=unusedFunction" is specified - see #10648
Expand Down Expand Up @@ -1514,6 +1516,8 @@ void CppCheck::executeAddons(const std::vector<std::string>& files, const std::s
if (isCtuInfo && addonInfo.name != "misra" && !addonInfo.ctu)
continue;

ProgressReporter progressReporter(mErrorLogger, mSettings.reportProgress, files.front(), "addon:" + addonInfo.name + (isCtuInfo ? " (ctu)" : ""));

std::vector<picojson::value> results;

try {
Expand Down
36 changes: 36 additions & 0 deletions lib/errorlogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <cstddef>
#include <cstdint>
#include <ctime>
#include <list>
#include <set>
#include <string>
Expand Down Expand Up @@ -286,6 +287,41 @@ class CPPCHECKLIB ErrorLogger {
static const std::set<std::string> mCriticalErrorIds;
};

/// RAII class for reporting progress messages
class CPPCHECKLIB ProgressReporter {
public:
ProgressReporter(ErrorLogger& e, int reportProgressInterval, std::string filename, std::string stage) :
mErrorLogger(e),
mReportProgressInterval(reportProgressInterval),
mFilename(std::move(filename)),
mStage(std::move(stage)) {
report(0);
}

~ProgressReporter() {
mErrorLogger.reportProgress(mFilename, mStage.c_str(), 100);
}

void report(int value) {
if (mReportProgressInterval < 0 || value == mLastValue)
return;
const std::time_t t = std::time(nullptr);
if (t >= mLastTime + mReportProgressInterval) {
mErrorLogger.reportProgress(mFilename, mStage.c_str(), value);
mLastTime = t;
mLastValue = value;
}
}

private:
ErrorLogger& mErrorLogger;
const int mReportProgressInterval;
const std::string mFilename;
const std::string mStage;
std::time_t mLastTime{0};
int mLastValue{-1};
};

/** Replace substring. Example replaceStr("1,NR,3", "NR", "2") => "1,2,3" */
std::string replaceStr(std::string s, const std::string &from, const std::string &to);

Expand Down
11 changes: 5 additions & 6 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,6 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
// Store current access in each scope (depends on evaluation progress)
std::map<const Scope*, AccessControl> access;

const bool doProgress = (mSettings.reportProgress != -1);

std::map<Scope *, std::set<std::string>> forwardDecls;

const std::function<Scope *(const Token *, Scope *)> findForwardDeclScope = [&](const Token *tok, Scope *startScope) {
Expand All @@ -200,13 +198,14 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
return it->second.count(tok->str()) > 0 ? startScope : nullptr;
};

ProgressReporter progressReporter(mErrorLogger, mSettings.reportProgress, mTokenizer.list.getSourceFilePath(), "SymbolDatabase (find all scopes)");

// find all scopes
for (const Token *tok = mTokenizer.tokens(); tok; tok = tok ? tok->next() : nullptr) {
// #5593 suggested to add here:
if (doProgress)
mErrorLogger.reportProgress(mTokenizer.list.getSourceFilePath(),
"SymbolDatabase",
tok->progressValue());

progressReporter.report(tok->progressValue());

// Locate next class
if ((tok->isCpp() && tok->isKeyword() &&
((Token::Match(tok, "class|struct|union|namespace ::| %name% final| {|:|::|<") &&
Expand Down
10 changes: 4 additions & 6 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1167,11 +1167,10 @@ void Tokenizer::simplifyTypedefCpp()
std::vector<Space> spaceInfo(1);

const std::time_t maxTime = mSettings.typedefMaxTime > 0 ? std::time(nullptr) + mSettings.typedefMaxTime: 0;
const bool doProgress = (mSettings.reportProgress != -1) && !list.getFiles().empty();
ProgressReporter progressReporter(mErrorLogger, mSettings.reportProgress, list.getSourceFilePath(), "Tokenize (typedef)");

for (Token *tok = list.front(); tok; tok = tok->next()) {
if (doProgress)
mErrorLogger.reportProgress(list.getFiles()[0], "Tokenize (typedef)", tok->progressValue());
progressReporter.report(tok->progressValue());

if (Settings::terminated())
return;
Expand Down Expand Up @@ -2932,11 +2931,10 @@ bool Tokenizer::simplifyUsing()
};
std::list<Using> usingList;

const bool doProgress = (mSettings.reportProgress != -1) && !list.getFiles().empty();
ProgressReporter progressReporter(mErrorLogger, mSettings.reportProgress, list.getSourceFilePath(), "Tokenize (using)");

for (Token *tok = list.front(); tok; tok = tok->next()) {
if (doProgress)
mErrorLogger.reportProgress(list.getFiles()[0], "Tokenize (using)", tok->progressValue());
progressReporter.report(tok->progressValue());

if (Settings::terminated())
return substitute;
Expand Down
4 changes: 4 additions & 0 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7202,7 +7202,9 @@ struct ValueFlowPassRunner {
std::size_t n = state.settings.vfOptions.maxIterations;
while (n > 0 && values != getTotalValues()) {
values = getTotalValues();
const std::string passnum = std::to_string(state.settings.vfOptions.maxIterations - n + 1);
if (std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
ProgressReporter progressReporter(state.errorLogger, state.settings.reportProgress >= 0, state.tokenlist.getSourceFilePath(), std::string("ValueFlow::") + pass->name() + (' ' + passnum));
return run(pass);
}))
return true;
Expand Down Expand Up @@ -7346,6 +7348,8 @@ void ValueFlow::setValues(TokenList& tokenlist,
const Settings& settings,
TimerResultsIntf* timerResults)
{
ProgressReporter progressReporter(errorLogger, settings.reportProgress, tokenlist.getSourceFilePath(), "ValueFlow");

for (Token* tok = tokenlist.front(); tok; tok = tok->next())
tok->clearValueFlow();

Expand Down
64 changes: 61 additions & 3 deletions test/cli/other_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,67 @@ def test_progress(tmpdir):
"progress: Tokenize (typedef) 62%\n"
"progress: Tokenize (typedef) 75%\n"
"progress: Tokenize (typedef) 87%\n"
"progress: SymbolDatabase 0%\n"
"progress: SymbolDatabase 12%\n"
"progress: SymbolDatabase 87%\n"
"progress: Tokenize (typedef) 100%\n"
"progress: SymbolDatabase (find all scopes) 0%\n"
"progress: SymbolDatabase (find all scopes) 12%\n"
"progress: SymbolDatabase (find all scopes) 87%\n"
"progress: SymbolDatabase (find all scopes) 100%\n"
"progress: ValueFlow 0%\n"
"progress: ValueFlow::valueFlowImpossibleValues(tokenlist, settings) 1 0%\n"
"progress: ValueFlow::valueFlowImpossibleValues(tokenlist, settings) 1 100%\n"
"progress: ValueFlow::valueFlowSymbolicOperators(symboldatabase, settings) 1 0%\n"
"progress: ValueFlow::valueFlowSymbolicOperators(symboldatabase, settings) 1 100%\n"
"progress: ValueFlow::valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 0%\n"
"progress: ValueFlow::valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 100%\n"
"progress: ValueFlow::valueFlowSymbolicInfer(symboldatabase, settings) 1 0%\n"
"progress: ValueFlow::valueFlowSymbolicInfer(symboldatabase, settings) 1 100%\n"
"progress: ValueFlow::valueFlowArrayBool(tokenlist, settings) 1 0%\n"
"progress: ValueFlow::valueFlowArrayBool(tokenlist, settings) 1 100%\n"
"progress: ValueFlow::valueFlowArrayElement(tokenlist, settings) 1 0%\n"
"progress: ValueFlow::valueFlowArrayElement(tokenlist, settings) 1 100%\n"
"progress: ValueFlow::valueFlowRightShift(tokenlist, settings) 1 0%\n"
"progress: ValueFlow::valueFlowRightShift(tokenlist, settings) 1 100%\n"
"progress: ValueFlow::valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 0%\n"
"progress: ValueFlow::valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 100%\n"
"progress: ValueFlow::valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 0%\n"
"progress: ValueFlow::valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 100%\n"
"progress: ValueFlow::valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 0%\n"
"progress: ValueFlow::valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 100%\n"
"progress: ValueFlow::valueFlowInferCondition(tokenlist, settings) 1 0%\n"
"progress: ValueFlow::valueFlowInferCondition(tokenlist, settings) 1 100%\n"
"progress: ValueFlow::valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowFunctionReturn(tokenlist, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowFunctionReturn(tokenlist, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowLifetime(tokenlist, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowLifetime(tokenlist, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowUninit(tokenlist, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowUninit(tokenlist, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowAfterMove(tokenlist, symboldatabase, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowAfterMove(tokenlist, symboldatabase, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowSmartPointer(tokenlist, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowSmartPointer(tokenlist, errorLogger, settings) 1 100%\n"
"progress: ValueFlow::valueFlowIterators(tokenlist, settings) 1 0%\n"
"progress: ValueFlow::valueFlowIterators(tokenlist, settings) 1 100%\n"
"progress: ValueFlow::valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 0%\n"
"progress: ValueFlow::valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 100%\n"
"progress: ValueFlow::valueFlowIteratorInfer(tokenlist, settings) 1 0%\n"
"progress: ValueFlow::valueFlowIteratorInfer(tokenlist, settings) 1 100%\n"
"progress: ValueFlow::valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 0%\n"
"progress: ValueFlow::valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions) 1 100%\n"
"progress: ValueFlow::valueFlowSafeFunctions(tokenlist, symboldatabase, errorLogger, settings) 1 0%\n"
"progress: ValueFlow::valueFlowSafeFunctions(tokenlist, symboldatabase, errorLogger, settings) 1 100%\n"
"progress: ValueFlow 100%\n"
"progress: Run checkers 0%\n"
"progress: Run checkers 100%\n"
)
assert stderr == ""

Expand Down
Loading