ValueFlow: Add pass runner to check timeout and report time (#4952)
This commit is contained in:
parent
269850a62d
commit
86757de4d5
2
Makefile
2
Makefile
|
@ -628,7 +628,7 @@ $(libcppdir)/tokenlist.o: lib/tokenlist.cpp externals/simplecpp/simplecpp.h lib/
|
||||||
$(libcppdir)/utils.o: lib/utils.cpp lib/config.h lib/utils.h
|
$(libcppdir)/utils.o: lib/utils.cpp lib/config.h lib/utils.h
|
||||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/utils.cpp
|
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/utils.cpp
|
||||||
|
|
||||||
$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/forwardanalyzer.h lib/importproject.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h
|
$(libcppdir)/valueflow.o: lib/valueflow.cpp lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/forwardanalyzer.h lib/importproject.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h
|
||||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp
|
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp
|
||||||
|
|
||||||
$(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h
|
$(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h
|
||||||
|
|
|
@ -544,7 +544,11 @@ unsigned int CppCheck::check(const std::string &path)
|
||||||
Tokenizer tokenizer(&mSettings, this);
|
Tokenizer tokenizer(&mSettings, this);
|
||||||
tokenizer.list.appendFileIfNew(path);
|
tokenizer.list.appendFileIfNew(path);
|
||||||
clangimport::parseClangAstDump(&tokenizer, ast);
|
clangimport::parseClangAstDump(&tokenizer, ast);
|
||||||
ValueFlow::setValues(&tokenizer.list, const_cast<SymbolDatabase *>(tokenizer.getSymbolDatabase()), this, &mSettings);
|
ValueFlow::setValues(&tokenizer.list,
|
||||||
|
const_cast<SymbolDatabase*>(tokenizer.getSymbolDatabase()),
|
||||||
|
this,
|
||||||
|
&mSettings,
|
||||||
|
&s_timerResults);
|
||||||
if (mSettings.debugnormal)
|
if (mSettings.debugnormal)
|
||||||
tokenizer.printDebugOutput(1);
|
tokenizer.printDebugOutput(1);
|
||||||
checkNormalTokens(tokenizer);
|
checkNormalTokens(tokenizer);
|
||||||
|
|
|
@ -3316,9 +3316,9 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration)
|
||||||
if (doValueFlow) {
|
if (doValueFlow) {
|
||||||
if (mTimerResults) {
|
if (mTimerResults) {
|
||||||
Timer t("Tokenizer::simplifyTokens1::ValueFlow", mSettings->showtime, mTimerResults);
|
Timer t("Tokenizer::simplifyTokens1::ValueFlow", mSettings->showtime, mTimerResults);
|
||||||
ValueFlow::setValues(&list, mSymbolDatabase, mErrorLogger, mSettings);
|
ValueFlow::setValues(&list, mSymbolDatabase, mErrorLogger, mSettings, mTimerResults);
|
||||||
} else {
|
} else {
|
||||||
ValueFlow::setValues(&list, mSymbolDatabase, mErrorLogger, mSettings);
|
ValueFlow::setValues(&list, mSymbolDatabase, mErrorLogger, mSettings, mTimerResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,7 @@
|
||||||
#include "sourcelocation.h"
|
#include "sourcelocation.h"
|
||||||
#include "standards.h"
|
#include "standards.h"
|
||||||
#include "symboldatabase.h"
|
#include "symboldatabase.h"
|
||||||
|
#include "timer.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "tokenlist.h"
|
#include "tokenlist.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -106,6 +107,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <chrono>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -9071,46 +9073,105 @@ const ValueFlow::Value *ValueFlow::valueFlowConstantFoldAST(Token *expr, const S
|
||||||
return expr && expr->hasKnownValue() ? &expr->values().front() : nullptr;
|
return expr && expr->hasKnownValue() ? &expr->values().front() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::size_t getTotalValues(TokenList *tokenlist)
|
struct ValueFlowState {
|
||||||
|
explicit ValueFlowState(TokenList* tokenlist = nullptr,
|
||||||
|
SymbolDatabase* symboldatabase = nullptr,
|
||||||
|
ErrorLogger* errorLogger = nullptr,
|
||||||
|
const Settings* settings = nullptr)
|
||||||
|
: tokenlist(tokenlist), symboldatabase(symboldatabase), errorLogger(errorLogger), settings(settings)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TokenList* tokenlist = nullptr;
|
||||||
|
SymbolDatabase* symboldatabase = nullptr;
|
||||||
|
ErrorLogger* errorLogger = nullptr;
|
||||||
|
const Settings* settings = nullptr;
|
||||||
|
std::set<const Scope*> skippedFunctions = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ValueFlowPass {
|
||||||
|
ValueFlowPass() = default;
|
||||||
|
ValueFlowPass(const ValueFlowPass&) = default;
|
||||||
|
// Name of pass
|
||||||
|
virtual const char* name() const = 0;
|
||||||
|
// Run the pass
|
||||||
|
virtual void run(const ValueFlowState& state) const = 0;
|
||||||
|
// Returns true if pass needs C++
|
||||||
|
virtual bool cpp() const = 0;
|
||||||
|
virtual ~ValueFlowPass() noexcept {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ValueFlowPassRunner {
|
||||||
|
using Clock = std::chrono::steady_clock;
|
||||||
|
using TimePoint = std::chrono::time_point<Clock>;
|
||||||
|
explicit ValueFlowPassRunner(ValueFlowState state, TimerResultsIntf* timerResults = nullptr)
|
||||||
|
: state(std::move(state)), stop(TimePoint::max()), timerResults(timerResults)
|
||||||
|
{
|
||||||
|
setSkippedFunctions();
|
||||||
|
setStopTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run_once(std::initializer_list<ValuePtr<ValueFlowPass>> passes) const
|
||||||
|
{
|
||||||
|
return std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
|
||||||
|
return run(pass);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(std::initializer_list<ValuePtr<ValueFlowPass>> passes) const
|
||||||
|
{
|
||||||
|
std::size_t values = 0;
|
||||||
|
std::size_t n = state.settings->valueFlowMaxIterations;
|
||||||
|
while (n > 0 && values != getTotalValues()) {
|
||||||
|
values = getTotalValues();
|
||||||
|
if (std::any_of(passes.begin(), passes.end(), [&](const ValuePtr<ValueFlowPass>& pass) {
|
||||||
|
return run(pass);
|
||||||
|
}))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (state.settings->debugwarnings) {
|
||||||
|
if (n == 0 && values != getTotalValues()) {
|
||||||
|
ErrorMessage::FileLocation loc;
|
||||||
|
loc.setfile(state.tokenlist->getFiles()[0]);
|
||||||
|
ErrorMessage errmsg({std::move(loc)},
|
||||||
|
emptyString,
|
||||||
|
Severity::debug,
|
||||||
|
"ValueFlow maximum iterations exceeded",
|
||||||
|
"valueFlowMaxIterations",
|
||||||
|
Certainty::normal);
|
||||||
|
state.errorLogger->reportErr(errmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(const ValuePtr<ValueFlowPass>& pass) const
|
||||||
|
{
|
||||||
|
auto start = Clock::now();
|
||||||
|
if (start > stop)
|
||||||
|
return true;
|
||||||
|
if (!state.tokenlist->isCPP() && pass->cpp())
|
||||||
|
return false;
|
||||||
|
if (timerResults) {
|
||||||
|
Timer t(pass->name(), state.settings->showtime, timerResults);
|
||||||
|
pass->run(state);
|
||||||
|
} else {
|
||||||
|
pass->run(state);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t getTotalValues() const
|
||||||
{
|
{
|
||||||
std::size_t n = 1;
|
std::size_t n = 1;
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next())
|
for (Token* tok = state.tokenlist->front(); tok; tok = tok->next())
|
||||||
n += tok->values().size();
|
n += tok->values().size();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::uint64_t getValueFlowStopTime(const Settings* settings) {
|
void setSkippedFunctions()
|
||||||
if (settings->performanceValueFlowMaxTime >= 0)
|
|
||||||
return std::time(nullptr) + settings->performanceValueFlowMaxTime;
|
|
||||||
return ~0ULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
|
||||||
{
|
{
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next())
|
if (state.settings->performanceValueFlowMaxIfCount > 0) {
|
||||||
tok->clearValueFlow();
|
for (const Scope* functionScope : state.symboldatabase->functionScopes) {
|
||||||
|
|
||||||
valueFlowEnumValue(symboldatabase, settings);
|
|
||||||
valueFlowNumber(tokenlist, settings);
|
|
||||||
valueFlowString(tokenlist, settings);
|
|
||||||
valueFlowArray(tokenlist, settings);
|
|
||||||
valueFlowUnknownFunctionReturn(tokenlist, settings);
|
|
||||||
valueFlowGlobalConstVar(tokenlist, settings);
|
|
||||||
valueFlowEnumValue(symboldatabase, settings);
|
|
||||||
valueFlowNumber(tokenlist, settings);
|
|
||||||
valueFlowGlobalStaticVar(tokenlist, settings);
|
|
||||||
valueFlowPointerAlias(tokenlist, settings);
|
|
||||||
valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings);
|
|
||||||
valueFlowSymbolic(tokenlist, symboldatabase, settings);
|
|
||||||
valueFlowBitAnd(tokenlist, settings);
|
|
||||||
valueFlowSameExpressions(tokenlist, settings);
|
|
||||||
valueFlowConditionExpressions(tokenlist, symboldatabase, errorLogger, *settings);
|
|
||||||
|
|
||||||
const std::uint64_t stopTime = getValueFlowStopTime(settings);
|
|
||||||
|
|
||||||
std::set<const Scope*> skippedFunctions;
|
|
||||||
if (settings->performanceValueFlowMaxIfCount > 0) {
|
|
||||||
for (const Scope* functionScope: symboldatabase->functionScopes) {
|
|
||||||
int countIfScopes = 0;
|
int countIfScopes = 0;
|
||||||
std::vector<const Scope*> scopes{functionScope};
|
std::vector<const Scope*> scopes{functionScope};
|
||||||
while (!scopes.empty()) {
|
while (!scopes.empty()) {
|
||||||
|
@ -9122,103 +9183,145 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
|
||||||
++countIfScopes;
|
++countIfScopes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (countIfScopes > settings->performanceValueFlowMaxIfCount) {
|
if (countIfScopes > state.settings->performanceValueFlowMaxIfCount) {
|
||||||
skippedFunctions.emplace(functionScope);
|
state.skippedFunctions.emplace(functionScope);
|
||||||
|
|
||||||
if (settings->severity.isEnabled(Severity::information)) {
|
if (state.settings->severity.isEnabled(Severity::information)) {
|
||||||
const std::string& functionName = functionScope->className;
|
const std::string& functionName = functionScope->className;
|
||||||
const std::list<ErrorMessage::FileLocation> callstack(1, ErrorMessage::FileLocation(functionScope->bodyStart, tokenlist));
|
const std::list<ErrorMessage::FileLocation> callstack(
|
||||||
const ErrorMessage errmsg(callstack, tokenlist->getSourceFilePath(), Severity::information,
|
1,
|
||||||
"ValueFlow analysis is limited in " + functionName + ". Use --check-level=exhaustive if full analysis is wanted.",
|
ErrorMessage::FileLocation(functionScope->bodyStart, state.tokenlist));
|
||||||
"checkLevelNormal", Certainty::normal);
|
const ErrorMessage errmsg(callstack,
|
||||||
errorLogger->reportErr(errmsg);
|
state.tokenlist->getSourceFilePath(),
|
||||||
}
|
Severity::information,
|
||||||
}
|
"ValueFlow analysis is limited in " + functionName +
|
||||||
}
|
". Use --check-level=exhaustive if full analysis is wanted.",
|
||||||
}
|
"checkLevelNormal",
|
||||||
|
|
||||||
std::size_t values = 0;
|
|
||||||
std::size_t n = settings->valueFlowMaxIterations;
|
|
||||||
while (n > 0 && values != getTotalValues(tokenlist)) {
|
|
||||||
values = getTotalValues(tokenlist);
|
|
||||||
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowImpossibleValues(tokenlist, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowSymbolicOperators(symboldatabase, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowSymbolicInfer(symboldatabase, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowArrayBool(tokenlist, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowArrayElement(tokenlist, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowRightShift(tokenlist, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowInferCondition(tokenlist, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, *settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowFunctionReturn(tokenlist, errorLogger, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowUninit(tokenlist, symboldatabase, settings);
|
|
||||||
|
|
||||||
if (tokenlist->isCPP()) {
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowAfterMove(tokenlist, symboldatabase, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowSmartPointer(tokenlist, errorLogger, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowIterators(tokenlist, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowIteratorInfer(tokenlist, settings);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions);
|
|
||||||
}
|
|
||||||
if (std::time(nullptr) < stopTime)
|
|
||||||
valueFlowSafeFunctions(tokenlist, symboldatabase, settings);
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings->debugwarnings) {
|
|
||||||
if (n == 0 && values != getTotalValues(tokenlist)) {
|
|
||||||
ErrorMessage::FileLocation loc;
|
|
||||||
loc.setfile(tokenlist->getFiles()[0]);
|
|
||||||
ErrorMessage errmsg({std::move(loc)},
|
|
||||||
emptyString,
|
|
||||||
Severity::debug,
|
|
||||||
"ValueFlow maximum iterations exceeded",
|
|
||||||
"valueFlowMaxIterations",
|
|
||||||
Certainty::normal);
|
Certainty::normal);
|
||||||
errorLogger->reportErr(errmsg);
|
state.errorLogger->reportErr(errmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::time(nullptr) < stopTime)
|
void setStopTime()
|
||||||
valueFlowDynamicBufferSize(tokenlist, symboldatabase, settings);
|
{
|
||||||
|
if (state.settings->performanceValueFlowMaxTime >= 0)
|
||||||
|
stop = Clock::now() + std::chrono::seconds{state.settings->performanceValueFlowMaxTime};
|
||||||
|
}
|
||||||
|
|
||||||
if (std::time(nullptr) < stopTime)
|
ValueFlowState state;
|
||||||
valueFlowDebug(tokenlist, errorLogger, settings);
|
TimePoint stop;
|
||||||
|
TimerResultsIntf* timerResults;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
struct ValueFlowPassAdaptor : ValueFlowPass {
|
||||||
|
const char* mName = nullptr;
|
||||||
|
bool mCPP = false;
|
||||||
|
F mRun;
|
||||||
|
ValueFlowPassAdaptor(const char* pname, bool pcpp, F prun) : mName(pname), mCPP(pcpp), mRun(prun) {}
|
||||||
|
const char* name() const override {
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
void run(const ValueFlowState& state) const override
|
||||||
|
{
|
||||||
|
mRun(state.tokenlist, state.symboldatabase, state.errorLogger, state.settings, state.skippedFunctions);
|
||||||
|
}
|
||||||
|
bool cpp() const override {
|
||||||
|
return mCPP;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
ValueFlowPassAdaptor<F> makeValueFlowPassAdaptor(const char* name, bool cpp, F run)
|
||||||
|
{
|
||||||
|
return {name, cpp, run};
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VALUEFLOW_ADAPTOR(cpp, ...) \
|
||||||
|
makeValueFlowPassAdaptor(#__VA_ARGS__, \
|
||||||
|
cpp, \
|
||||||
|
[](TokenList* tokenlist, \
|
||||||
|
SymbolDatabase* symboldatabase, \
|
||||||
|
ErrorLogger* errorLogger, \
|
||||||
|
const Settings* settings, \
|
||||||
|
const std::set<const Scope*>& skippedFunctions) { \
|
||||||
|
(void)tokenlist; \
|
||||||
|
(void)symboldatabase; \
|
||||||
|
(void)errorLogger; \
|
||||||
|
(void)settings; \
|
||||||
|
(void)skippedFunctions; \
|
||||||
|
__VA_ARGS__; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define VFA(...) VALUEFLOW_ADAPTOR(false, __VA_ARGS__)
|
||||||
|
#define VFA_CPP(...) VALUEFLOW_ADAPTOR(true, __VA_ARGS__)
|
||||||
|
|
||||||
|
void ValueFlow::setValues(TokenList* tokenlist,
|
||||||
|
SymbolDatabase* symboldatabase,
|
||||||
|
ErrorLogger* errorLogger,
|
||||||
|
const Settings* settings,
|
||||||
|
TimerResultsIntf* timerResults)
|
||||||
|
{
|
||||||
|
for (Token* tok = tokenlist->front(); tok; tok = tok->next())
|
||||||
|
tok->clearValueFlow();
|
||||||
|
|
||||||
|
ValueFlowPassRunner runner{ValueFlowState{tokenlist, symboldatabase, errorLogger, settings}, timerResults};
|
||||||
|
runner.run_once({
|
||||||
|
VFA(valueFlowEnumValue(symboldatabase, settings)),
|
||||||
|
VFA(valueFlowNumber(tokenlist, settings)),
|
||||||
|
VFA(valueFlowString(tokenlist, settings)),
|
||||||
|
VFA(valueFlowArray(tokenlist, settings)),
|
||||||
|
VFA(valueFlowUnknownFunctionReturn(tokenlist, settings)),
|
||||||
|
VFA(valueFlowGlobalConstVar(tokenlist, settings)),
|
||||||
|
VFA(valueFlowEnumValue(symboldatabase, settings)),
|
||||||
|
VFA(valueFlowNumber(tokenlist, settings)),
|
||||||
|
VFA(valueFlowGlobalStaticVar(tokenlist, settings)),
|
||||||
|
VFA(valueFlowPointerAlias(tokenlist, settings)),
|
||||||
|
VFA(valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings)),
|
||||||
|
VFA(valueFlowSymbolic(tokenlist, symboldatabase, settings)),
|
||||||
|
VFA(valueFlowBitAnd(tokenlist, settings)),
|
||||||
|
VFA(valueFlowSameExpressions(tokenlist, settings)),
|
||||||
|
VFA(valueFlowConditionExpressions(tokenlist, symboldatabase, errorLogger, *settings)),
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.run({
|
||||||
|
VFA(valueFlowImpossibleValues(tokenlist, settings)),
|
||||||
|
VFA(valueFlowSymbolicOperators(symboldatabase, settings)),
|
||||||
|
VFA(valueFlowCondition(SymbolicConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
|
||||||
|
VFA(valueFlowSymbolicInfer(symboldatabase, settings)),
|
||||||
|
VFA(valueFlowArrayBool(tokenlist, settings)),
|
||||||
|
VFA(valueFlowArrayElement(tokenlist, settings)),
|
||||||
|
VFA(valueFlowRightShift(tokenlist, settings)),
|
||||||
|
VFA(valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
|
||||||
|
VFA_CPP(valueFlowAfterSwap(tokenlist, symboldatabase, errorLogger, settings)),
|
||||||
|
VFA(valueFlowCondition(SimpleConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
|
||||||
|
VFA(valueFlowInferCondition(tokenlist, settings)),
|
||||||
|
VFA(valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings)),
|
||||||
|
VFA(valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings)),
|
||||||
|
VFA(valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, *settings)),
|
||||||
|
VFA(valueFlowFunctionReturn(tokenlist, errorLogger, settings)),
|
||||||
|
VFA(valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings)),
|
||||||
|
VFA(valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, settings)),
|
||||||
|
VFA(valueFlowUninit(tokenlist, symboldatabase, settings)),
|
||||||
|
VFA_CPP(valueFlowAfterMove(tokenlist, symboldatabase, settings)),
|
||||||
|
VFA_CPP(valueFlowSmartPointer(tokenlist, errorLogger, settings)),
|
||||||
|
VFA_CPP(valueFlowIterators(tokenlist, settings)),
|
||||||
|
VFA_CPP(
|
||||||
|
valueFlowCondition(IteratorConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
|
||||||
|
VFA_CPP(valueFlowIteratorInfer(tokenlist, settings)),
|
||||||
|
VFA_CPP(valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
|
||||||
|
VFA_CPP(
|
||||||
|
valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)),
|
||||||
|
VFA(valueFlowSafeFunctions(tokenlist, symboldatabase, settings)),
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.run_once({
|
||||||
|
VFA(valueFlowDynamicBufferSize(tokenlist, symboldatabase, settings)),
|
||||||
|
VFA(valueFlowDebug(tokenlist, errorLogger, settings)),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ValueFlow::eitherTheConditionIsRedundant(const Token *condition)
|
std::string ValueFlow::eitherTheConditionIsRedundant(const Token *condition)
|
||||||
|
|
|
@ -36,6 +36,7 @@ class ErrorLogger;
|
||||||
struct InferModel;
|
struct InferModel;
|
||||||
class Settings;
|
class Settings;
|
||||||
class SymbolDatabase;
|
class SymbolDatabase;
|
||||||
|
class TimerResultsIntf;
|
||||||
class Token;
|
class Token;
|
||||||
class TokenList;
|
class TokenList;
|
||||||
class ValueType;
|
class ValueType;
|
||||||
|
@ -50,7 +51,11 @@ namespace ValueFlow {
|
||||||
const Value * valueFlowConstantFoldAST(Token *expr, const Settings *settings);
|
const Value * valueFlowConstantFoldAST(Token *expr, const Settings *settings);
|
||||||
|
|
||||||
/// Perform valueflow analysis.
|
/// Perform valueflow analysis.
|
||||||
void setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings);
|
void setValues(TokenList* tokenlist,
|
||||||
|
SymbolDatabase* symboldatabase,
|
||||||
|
ErrorLogger* errorLogger,
|
||||||
|
const Settings* settings,
|
||||||
|
TimerResultsIntf* timerResults);
|
||||||
|
|
||||||
std::string eitherTheConditionIsRedundant(const Token *condition);
|
std::string eitherTheConditionIsRedundant(const Token *condition);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue