avoid some unchecked pointer dereferences (#4811)
This commit is contained in:
parent
215124461e
commit
b70e1d5461
|
@ -81,7 +81,7 @@ static bool addFilesToList(const std::string& fileList, std::vector<std::string>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool addIncludePathsToList(const std::string& fileList, std::list<std::string>* pathNames)
|
static bool addIncludePathsToList(const std::string& fileList, std::list<std::string>& pathNames)
|
||||||
{
|
{
|
||||||
std::ifstream files(fileList);
|
std::ifstream files(fileList);
|
||||||
if (files) {
|
if (files) {
|
||||||
|
@ -96,7 +96,7 @@ static bool addIncludePathsToList(const std::string& fileList, std::list<std::st
|
||||||
if (!endsWith(pathName, '/'))
|
if (!endsWith(pathName, '/'))
|
||||||
pathName += '/';
|
pathName += '/';
|
||||||
|
|
||||||
pathNames->emplace_back(std::move(pathName));
|
pathNames.emplace_back(std::move(pathName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -104,12 +104,12 @@ static bool addIncludePathsToList(const std::string& fileList, std::list<std::st
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool addPathsToSet(const std::string& fileName, std::set<std::string>* set)
|
static bool addPathsToSet(const std::string& fileName, std::set<std::string>& set)
|
||||||
{
|
{
|
||||||
std::list<std::string> templist;
|
std::list<std::string> templist;
|
||||||
if (!addIncludePathsToList(fileName, &templist))
|
if (!addIncludePathsToList(fileName, templist))
|
||||||
return false;
|
return false;
|
||||||
set->insert(templist.cbegin(), templist.cend());
|
set.insert(templist.cbegin(), templist.cend());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
else if (std::strncmp(argv[i], "--config-excludes-file=", 23) == 0) {
|
else if (std::strncmp(argv[i], "--config-excludes-file=", 23) == 0) {
|
||||||
// open this file and read every input file (1 file name per line)
|
// open this file and read every input file (1 file name per line)
|
||||||
const std::string cfgExcludesFile(23 + argv[i]);
|
const std::string cfgExcludesFile(23 + argv[i]);
|
||||||
if (!addPathsToSet(cfgExcludesFile, &mSettings->configExcludePaths)) {
|
if (!addPathsToSet(cfgExcludesFile, mSettings->configExcludePaths)) {
|
||||||
printError("unable to open config excludes file at '" + cfgExcludesFile + "'");
|
printError("unable to open config excludes file at '" + cfgExcludesFile + "'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -468,7 +468,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
else if (std::strncmp(argv[i], "--includes-file=", 16) == 0) {
|
else if (std::strncmp(argv[i], "--includes-file=", 16) == 0) {
|
||||||
// open this file and read every input file (1 file name per line)
|
// open this file and read every input file (1 file name per line)
|
||||||
const std::string includesFile(16 + argv[i]);
|
const std::string includesFile(16 + argv[i]);
|
||||||
if (!addIncludePathsToList(includesFile, &mSettings->includePaths)) {
|
if (!addIncludePathsToList(includesFile, mSettings->includePaths)) {
|
||||||
printError("unable to open includes file at '" + includesFile + "'");
|
printError("unable to open includes file at '" + includesFile + "'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -568,9 +568,9 @@ bool CppCheckExecutor::tryLoadLibrary(Library& destination, const std::string& b
|
||||||
*/
|
*/
|
||||||
// cppcheck-suppress passedByValue - used as callback so we need to preserve the signature
|
// cppcheck-suppress passedByValue - used as callback so we need to preserve the signature
|
||||||
// NOLINTNEXTLINE(performance-unnecessary-value-param) - used as callback so we need to preserve the signature
|
// NOLINTNEXTLINE(performance-unnecessary-value-param) - used as callback so we need to preserve the signature
|
||||||
bool CppCheckExecutor::executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string *output_)
|
bool CppCheckExecutor::executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output_)
|
||||||
{
|
{
|
||||||
output_->clear();
|
output_.clear();
|
||||||
|
|
||||||
std::string joinedArgs;
|
std::string joinedArgs;
|
||||||
for (const std::string &arg : args) {
|
for (const std::string &arg : args) {
|
||||||
|
@ -596,7 +596,7 @@ bool CppCheckExecutor::executeCommand(std::string exe, std::vector<std::string>
|
||||||
return false;
|
return false;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr)
|
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr)
|
||||||
*output_ += buffer;
|
output_ += buffer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Execute a shell command and read the output from it. Returns true if command terminated successfully.
|
* Execute a shell command and read the output from it. Returns true if command terminated successfully.
|
||||||
*/
|
*/
|
||||||
static bool executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string *output_);
|
static bool executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output_);
|
||||||
|
|
||||||
static bool reportSuppressions(const Settings &settings, bool unusedFunctionCheckEnabled, const std::map<std::string, std::size_t> &files, ErrorLogger& errorLogger);
|
static bool reportSuppressions(const Settings &settings, bool unusedFunctionCheckEnabled, const std::map<std::string, std::size_t> &files, ErrorLogger& errorLogger);
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,9 @@
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
// NOLINTNEXTLINE(performance-unnecessary-value-param) - used as callback so we need to preserve the signature
|
// NOLINTNEXTLINE(performance-unnecessary-value-param) - used as callback so we need to preserve the signature
|
||||||
static bool executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string *output)
|
static bool executeCommand(std::string exe, std::vector<std::string> args, std::string redirect, std::string &output)
|
||||||
{
|
{
|
||||||
output->clear();
|
output.clear();
|
||||||
|
|
||||||
QStringList args2;
|
QStringList args2;
|
||||||
for (const std::string &arg: args)
|
for (const std::string &arg: args)
|
||||||
|
@ -60,9 +60,9 @@ static bool executeCommand(std::string exe, std::vector<std::string> args, std::
|
||||||
if (redirect == "2>&1") {
|
if (redirect == "2>&1") {
|
||||||
QString s1 = process.readAllStandardOutput();
|
QString s1 = process.readAllStandardOutput();
|
||||||
QString s2 = process.readAllStandardError();
|
QString s2 = process.readAllStandardError();
|
||||||
*output = (s1 + "\n" + s2).toStdString();
|
output = (s1 + "\n" + s2).toStdString();
|
||||||
} else
|
} else
|
||||||
*output = process.readAllStandardOutput().toStdString();
|
output = process.readAllStandardOutput().toStdString();
|
||||||
|
|
||||||
if (redirect.compare(0,3,"2> ") == 0) {
|
if (redirect.compare(0,3,"2> ") == 0) {
|
||||||
std::ofstream fout(redirect.substr(3));
|
std::ofstream fout(redirect.substr(3));
|
||||||
|
|
|
@ -72,7 +72,7 @@ void AnalyzerInformation::close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool skipAnalysis(const std::string &analyzerInfoFile, std::size_t hash, std::list<ErrorMessage> *errors)
|
static bool skipAnalysis(const std::string &analyzerInfoFile, std::size_t hash, std::list<ErrorMessage> &errors)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLDocument doc;
|
tinyxml2::XMLDocument doc;
|
||||||
const tinyxml2::XMLError error = doc.LoadFile(analyzerInfoFile.c_str());
|
const tinyxml2::XMLError error = doc.LoadFile(analyzerInfoFile.c_str());
|
||||||
|
@ -89,7 +89,7 @@ static bool skipAnalysis(const std::string &analyzerInfoFile, std::size_t hash,
|
||||||
|
|
||||||
for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
||||||
if (std::strcmp(e->Name(), "error") == 0)
|
if (std::strcmp(e->Name(), "error") == 0)
|
||||||
errors->emplace_back(e);
|
errors.emplace_back(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -127,7 +127,7 @@ std::string AnalyzerInformation::getAnalyzerInfoFile(const std::string &buildDir
|
||||||
return Path::join(buildDir, filename) + ".analyzerinfo";
|
return Path::join(buildDir, filename) + ".analyzerinfo";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t hash, std::list<ErrorMessage> *errors)
|
bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t hash, std::list<ErrorMessage> &errors)
|
||||||
{
|
{
|
||||||
if (buildDir.empty() || sourcefile.empty())
|
if (buildDir.empty() || sourcefile.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
|
|
||||||
/** Close current TU.analyzerinfo file */
|
/** Close current TU.analyzerinfo file */
|
||||||
void close();
|
void close();
|
||||||
bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t hash, std::list<ErrorMessage> *errors);
|
bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t hash, std::list<ErrorMessage> &errors);
|
||||||
void reportErr(const ErrorMessage &msg);
|
void reportErr(const ErrorMessage &msg);
|
||||||
void setFileInfo(const std::string &check, const std::string &fileInfo);
|
void setFileInfo(const std::string &check, const std::string &fileInfo);
|
||||||
static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg);
|
static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg);
|
||||||
|
|
|
@ -109,7 +109,7 @@ static int getArgumentPos(const Token* ftok, const Token* tokToFind){
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, REQUIRES("T must be a Token class", std::is_convertible<T*, const Token*> )>
|
template<class T, REQUIRES("T must be a Token class", std::is_convertible<T*, const Token*> )>
|
||||||
static void astFlattenRecursive(T* tok, std::vector<T*>* result, const char* op, nonneg int depth = 0)
|
static void astFlattenRecursive(T* tok, std::vector<T*>& result, const char* op, nonneg int depth = 0)
|
||||||
{
|
{
|
||||||
++depth;
|
++depth;
|
||||||
if (!tok || depth >= 100)
|
if (!tok || depth >= 100)
|
||||||
|
@ -118,21 +118,21 @@ static void astFlattenRecursive(T* tok, std::vector<T*>* result, const char* op,
|
||||||
astFlattenRecursive(tok->astOperand1(), result, op, depth);
|
astFlattenRecursive(tok->astOperand1(), result, op, depth);
|
||||||
astFlattenRecursive(tok->astOperand2(), result, op, depth);
|
astFlattenRecursive(tok->astOperand2(), result, op, depth);
|
||||||
} else {
|
} else {
|
||||||
result->push_back(tok);
|
result.push_back(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<const Token*> astFlatten(const Token* tok, const char* op)
|
std::vector<const Token*> astFlatten(const Token* tok, const char* op)
|
||||||
{
|
{
|
||||||
std::vector<const Token*> result;
|
std::vector<const Token*> result;
|
||||||
astFlattenRecursive(tok, &result, op);
|
astFlattenRecursive(tok, result, op);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Token*> astFlatten(Token* tok, const char* op)
|
std::vector<Token*> astFlatten(Token* tok, const char* op)
|
||||||
{
|
{
|
||||||
std::vector<Token*> result;
|
std::vector<Token*> result;
|
||||||
astFlattenRecursive(tok, &result, op);
|
astFlattenRecursive(tok, result, op);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,12 +865,12 @@ const Token *findNextTokenFromBreak(const Token *breakToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool extractForLoopValues(const Token *forToken,
|
bool extractForLoopValues(const Token *forToken,
|
||||||
nonneg int * const varid,
|
nonneg int &varid,
|
||||||
bool * const knownInitValue,
|
bool &knownInitValue,
|
||||||
MathLib::bigint * const initValue,
|
MathLib::bigint &initValue,
|
||||||
bool * const partialCond,
|
bool &partialCond,
|
||||||
MathLib::bigint * const stepValue,
|
MathLib::bigint &stepValue,
|
||||||
MathLib::bigint * const lastValue)
|
MathLib::bigint &lastValue)
|
||||||
{
|
{
|
||||||
if (!Token::simpleMatch(forToken, "for (") || !Token::simpleMatch(forToken->next()->astOperand2(), ";"))
|
if (!Token::simpleMatch(forToken, "for (") || !Token::simpleMatch(forToken->next()->astOperand2(), ";"))
|
||||||
return false;
|
return false;
|
||||||
|
@ -880,28 +880,28 @@ bool extractForLoopValues(const Token *forToken,
|
||||||
if (!initExpr || !initExpr->isBinaryOp() || initExpr->str() != "=" || !Token::Match(initExpr->astOperand1(), "%var%"))
|
if (!initExpr || !initExpr->isBinaryOp() || initExpr->str() != "=" || !Token::Match(initExpr->astOperand1(), "%var%"))
|
||||||
return false;
|
return false;
|
||||||
std::vector<MathLib::bigint> minInitValue = getMinValue(ValueFlow::makeIntegralInferModel(), initExpr->astOperand2()->values());
|
std::vector<MathLib::bigint> minInitValue = getMinValue(ValueFlow::makeIntegralInferModel(), initExpr->astOperand2()->values());
|
||||||
*varid = initExpr->astOperand1()->varId();
|
varid = initExpr->astOperand1()->varId();
|
||||||
*knownInitValue = initExpr->astOperand2()->hasKnownIntValue();
|
knownInitValue = initExpr->astOperand2()->hasKnownIntValue();
|
||||||
*initValue = minInitValue.empty() ? 0 : minInitValue.front();
|
initValue = minInitValue.empty() ? 0 : minInitValue.front();
|
||||||
*partialCond = Token::Match(condExpr, "%oror%|&&");
|
partialCond = Token::Match(condExpr, "%oror%|&&");
|
||||||
visitAstNodes(condExpr, [varid, &condExpr](const Token *tok) {
|
visitAstNodes(condExpr, [varid, &condExpr](const Token *tok) {
|
||||||
if (Token::Match(tok, "%oror%|&&"))
|
if (Token::Match(tok, "%oror%|&&"))
|
||||||
return ChildrenToVisit::op1_and_op2;
|
return ChildrenToVisit::op1_and_op2;
|
||||||
if (Token::Match(tok, "<|<=") && tok->isBinaryOp() && tok->astOperand1()->varId() == *varid && tok->astOperand2()->hasKnownIntValue()) {
|
if (Token::Match(tok, "<|<=") && tok->isBinaryOp() && tok->astOperand1()->varId() == varid && tok->astOperand2()->hasKnownIntValue()) {
|
||||||
if (Token::Match(condExpr, "%oror%|&&") || tok->astOperand2()->getKnownIntValue() < condExpr->astOperand2()->getKnownIntValue())
|
if (Token::Match(condExpr, "%oror%|&&") || tok->astOperand2()->getKnownIntValue() < condExpr->astOperand2()->getKnownIntValue())
|
||||||
condExpr = tok;
|
condExpr = tok;
|
||||||
}
|
}
|
||||||
return ChildrenToVisit::none;
|
return ChildrenToVisit::none;
|
||||||
});
|
});
|
||||||
if (!Token::Match(condExpr, "<|<=") || !condExpr->isBinaryOp() || condExpr->astOperand1()->varId() != *varid || !condExpr->astOperand2()->hasKnownIntValue())
|
if (!Token::Match(condExpr, "<|<=") || !condExpr->isBinaryOp() || condExpr->astOperand1()->varId() != varid || !condExpr->astOperand2()->hasKnownIntValue())
|
||||||
return false;
|
return false;
|
||||||
if (!incExpr || !incExpr->isUnaryOp("++") || incExpr->astOperand1()->varId() != *varid)
|
if (!incExpr || !incExpr->isUnaryOp("++") || incExpr->astOperand1()->varId() != varid)
|
||||||
return false;
|
return false;
|
||||||
*stepValue = 1;
|
stepValue = 1;
|
||||||
if (condExpr->str() == "<")
|
if (condExpr->str() == "<")
|
||||||
*lastValue = condExpr->astOperand2()->getKnownIntValue() - 1;
|
lastValue = condExpr->astOperand2()->getKnownIntValue() - 1;
|
||||||
else
|
else
|
||||||
*lastValue = condExpr->astOperand2()->getKnownIntValue();
|
lastValue = condExpr->astOperand2()->getKnownIntValue();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,12 +216,12 @@ const Token *findNextTokenFromBreak(const Token *breakToken);
|
||||||
* Extract for loop values: loopvar varid, init value, step value, last value (inclusive)
|
* Extract for loop values: loopvar varid, init value, step value, last value (inclusive)
|
||||||
*/
|
*/
|
||||||
bool extractForLoopValues(const Token *forToken,
|
bool extractForLoopValues(const Token *forToken,
|
||||||
nonneg int * const varid,
|
nonneg int &varid,
|
||||||
bool * const knownInitValue,
|
bool &knownInitValue,
|
||||||
long long * const initValue,
|
long long &initValue,
|
||||||
bool * const partialCond,
|
bool &partialCond,
|
||||||
long long * const stepValue,
|
long long &stepValue,
|
||||||
long long * const lastValue);
|
long long &lastValue);
|
||||||
|
|
||||||
bool precedes(const Token * tok1, const Token * tok2);
|
bool precedes(const Token * tok1, const Token * tok2);
|
||||||
bool succeeds(const Token* tok1, const Token* tok2);
|
bool succeeds(const Token* tok1, const Token* tok2);
|
||||||
|
|
|
@ -183,37 +183,36 @@ static int getMinFormatStringOutputLength(const std::vector<const Token*> ¶m
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
static bool getDimensionsEtc(const Token * const arrayToken, const Settings *settings, std::vector<Dimension> * const dimensions, ErrorPath * const errorPath, bool * const mightBeLarger, MathLib::bigint* path)
|
static bool getDimensionsEtc(const Token * const arrayToken, const Settings *settings, std::vector<Dimension> &dimensions, ErrorPath &errorPath, bool &mightBeLarger, MathLib::bigint &path)
|
||||||
{
|
{
|
||||||
const Token *array = arrayToken;
|
const Token *array = arrayToken;
|
||||||
while (Token::Match(array, ".|::"))
|
while (Token::Match(array, ".|::"))
|
||||||
array = array->astOperand2();
|
array = array->astOperand2();
|
||||||
|
|
||||||
if (array->variable() && array->variable()->isArray() && !array->variable()->dimensions().empty()) {
|
if (array->variable() && array->variable()->isArray() && !array->variable()->dimensions().empty()) {
|
||||||
*dimensions = array->variable()->dimensions();
|
dimensions = array->variable()->dimensions();
|
||||||
if (dimensions->size() >= 1 && ((*dimensions)[0].num <= 1 || !(*dimensions)[0].tok)) {
|
if (dimensions[0].num <= 1 || !dimensions[0].tok) {
|
||||||
visitAstNodes(arrayToken,
|
visitAstNodes(arrayToken,
|
||||||
[&](const Token *child) {
|
[&](const Token *child) {
|
||||||
if (child->originalName() == "->") {
|
if (child->originalName() == "->") {
|
||||||
*mightBeLarger = true;
|
mightBeLarger = true;
|
||||||
return ChildrenToVisit::none;
|
return ChildrenToVisit::none;
|
||||||
}
|
}
|
||||||
return ChildrenToVisit::op1_and_op2;
|
return ChildrenToVisit::op1_and_op2;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (const Token *stringLiteral = array->getValueTokenMinStrSize(settings, path)) {
|
} else if (const Token *stringLiteral = array->getValueTokenMinStrSize(settings, &path)) {
|
||||||
Dimension dim;
|
Dimension dim;
|
||||||
dim.tok = nullptr;
|
dim.tok = nullptr;
|
||||||
dim.num = Token::getStrArraySize(stringLiteral);
|
dim.num = Token::getStrArraySize(stringLiteral);
|
||||||
dim.known = array->hasKnownValue();
|
dim.known = array->hasKnownValue();
|
||||||
dimensions->emplace_back(dim);
|
dimensions.emplace_back(dim);
|
||||||
} else if (array->valueType() && array->valueType()->pointer >= 1 && (array->valueType()->isIntegral() || array->valueType()->isFloat())) {
|
} else if (array->valueType() && array->valueType()->pointer >= 1 && (array->valueType()->isIntegral() || array->valueType()->isFloat())) {
|
||||||
const ValueFlow::Value *value = getBufferSizeValue(array);
|
const ValueFlow::Value *value = getBufferSizeValue(array);
|
||||||
if (!value)
|
if (!value)
|
||||||
return false;
|
return false;
|
||||||
if (path)
|
path = value->path;
|
||||||
*path = value->path;
|
errorPath = value->errorPath;
|
||||||
*errorPath = value->errorPath;
|
|
||||||
Dimension dim;
|
Dimension dim;
|
||||||
dim.known = value->isKnown();
|
dim.known = value->isKnown();
|
||||||
dim.tok = nullptr;
|
dim.tok = nullptr;
|
||||||
|
@ -221,9 +220,9 @@ static bool getDimensionsEtc(const Token * const arrayToken, const Settings *set
|
||||||
if (typeSize == 0)
|
if (typeSize == 0)
|
||||||
return false;
|
return false;
|
||||||
dim.num = value->intvalue / typeSize;
|
dim.num = value->intvalue / typeSize;
|
||||||
dimensions->emplace_back(dim);
|
dimensions.emplace_back(dim);
|
||||||
}
|
}
|
||||||
return !dimensions->empty();
|
return !dimensions.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
static ValueFlow::Value makeSizeValue(MathLib::bigint size, MathLib::bigint path)
|
static ValueFlow::Value makeSizeValue(MathLib::bigint size, MathLib::bigint path)
|
||||||
|
@ -314,7 +313,7 @@ void CheckBufferOverrun::arrayIndex()
|
||||||
ErrorPath errorPath;
|
ErrorPath errorPath;
|
||||||
bool mightBeLarger = false;
|
bool mightBeLarger = false;
|
||||||
MathLib::bigint path = 0;
|
MathLib::bigint path = 0;
|
||||||
if (!getDimensionsEtc(tok->astOperand1(), mSettings, &dimensions, &errorPath, &mightBeLarger, &path))
|
if (!getDimensionsEtc(tok->astOperand1(), mSettings, dimensions, errorPath, mightBeLarger, path))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Variable* const var = array->variable();
|
const Variable* const var = array->variable();
|
||||||
|
@ -486,7 +485,7 @@ void CheckBufferOverrun::pointerArithmetic()
|
||||||
ErrorPath errorPath;
|
ErrorPath errorPath;
|
||||||
bool mightBeLarger = false;
|
bool mightBeLarger = false;
|
||||||
MathLib::bigint path = 0;
|
MathLib::bigint path = 0;
|
||||||
if (!getDimensionsEtc(arrayToken, mSettings, &dimensions, &errorPath, &mightBeLarger, &path))
|
if (!getDimensionsEtc(arrayToken, mSettings, dimensions, errorPath, mightBeLarger, path))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tok->str() == "+") {
|
if (tok->str() == "+") {
|
||||||
|
@ -881,6 +880,8 @@ std::string CheckBufferOverrun::MyFileInfo::toString() const
|
||||||
|
|
||||||
bool CheckBufferOverrun::isCtuUnsafeBufferUsage(const Check *check, const Token *argtok, MathLib::bigint *offset, int type)
|
bool CheckBufferOverrun::isCtuUnsafeBufferUsage(const Check *check, const Token *argtok, MathLib::bigint *offset, int type)
|
||||||
{
|
{
|
||||||
|
if (!offset)
|
||||||
|
return false;
|
||||||
const CheckBufferOverrun *c = dynamic_cast<const CheckBufferOverrun *>(check);
|
const CheckBufferOverrun *c = dynamic_cast<const CheckBufferOverrun *>(check);
|
||||||
if (!c)
|
if (!c)
|
||||||
return false;
|
return false;
|
||||||
|
@ -897,8 +898,6 @@ bool CheckBufferOverrun::isCtuUnsafeBufferUsage(const Check *check, const Token
|
||||||
return false;
|
return false;
|
||||||
if (!indexTok->hasKnownIntValue())
|
if (!indexTok->hasKnownIntValue())
|
||||||
return false;
|
return false;
|
||||||
if (!offset)
|
|
||||||
return false;
|
|
||||||
*offset = indexTok->getKnownIntValue() * argtok->valueType()->typeSize(*c->mSettings);
|
*offset = indexTok->getKnownIntValue() * argtok->valueType()->typeSize(*c->mSettings);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1004,11 +1004,11 @@ static inline T getvalue(const int test, const T value1, const T value2)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parseComparison(const Token *comp, bool *not1, std::string *op, std::string *value, const Token **expr, bool* inconclusive)
|
static bool parseComparison(const Token *comp, bool ¬1, std::string &op, std::string &value, const Token *&expr, bool &inconclusive)
|
||||||
{
|
{
|
||||||
*not1 = false;
|
not1 = false;
|
||||||
while (comp && comp->str() == "!") {
|
while (comp && comp->str() == "!") {
|
||||||
*not1 = !(*not1);
|
not1 = !(not1);
|
||||||
comp = comp->astOperand1();
|
comp = comp->astOperand1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1018,37 +1018,37 @@ static bool parseComparison(const Token *comp, bool *not1, std::string *op, std:
|
||||||
const Token* op1 = comp->astOperand1();
|
const Token* op1 = comp->astOperand1();
|
||||||
const Token* op2 = comp->astOperand2();
|
const Token* op2 = comp->astOperand2();
|
||||||
if (!comp->isComparisonOp() || !op1 || !op2) {
|
if (!comp->isComparisonOp() || !op1 || !op2) {
|
||||||
*op = "!=";
|
op = "!=";
|
||||||
*value = "0";
|
value = "0";
|
||||||
*expr = comp;
|
expr = comp;
|
||||||
} else if (op1->isLiteral()) {
|
} else if (op1->isLiteral()) {
|
||||||
if (op1->isExpandedMacro())
|
if (op1->isExpandedMacro())
|
||||||
return false;
|
return false;
|
||||||
*op = invertOperatorForOperandSwap(comp->str());
|
op = invertOperatorForOperandSwap(comp->str());
|
||||||
if (op1->enumerator() && op1->enumerator()->value_known)
|
if (op1->enumerator() && op1->enumerator()->value_known)
|
||||||
*value = MathLib::toString(op1->enumerator()->value);
|
value = MathLib::toString(op1->enumerator()->value);
|
||||||
else
|
else
|
||||||
*value = op1->str();
|
value = op1->str();
|
||||||
*expr = op2;
|
expr = op2;
|
||||||
} else if (comp->astOperand2()->isLiteral()) {
|
} else if (comp->astOperand2()->isLiteral()) {
|
||||||
if (op2->isExpandedMacro())
|
if (op2->isExpandedMacro())
|
||||||
return false;
|
return false;
|
||||||
*op = comp->str();
|
op = comp->str();
|
||||||
if (op2->enumerator() && op2->enumerator()->value_known)
|
if (op2->enumerator() && op2->enumerator()->value_known)
|
||||||
*value = MathLib::toString(op2->enumerator()->value);
|
value = MathLib::toString(op2->enumerator()->value);
|
||||||
else
|
else
|
||||||
*value = op2->str();
|
value = op2->str();
|
||||||
*expr = op1;
|
expr = op1;
|
||||||
} else {
|
} else {
|
||||||
*op = "!=";
|
op = "!=";
|
||||||
*value = "0";
|
value = "0";
|
||||||
*expr = comp;
|
expr = comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
*inconclusive = *inconclusive || ((*value)[0] == '\'' && !(*op == "!=" || *op == "=="));
|
inconclusive = inconclusive || ((value)[0] == '\'' && !(op == "!=" || op == "=="));
|
||||||
|
|
||||||
// Only float and int values are currently handled
|
// Only float and int values are currently handled
|
||||||
if (!MathLib::isInt(*value) && !MathLib::isFloat(*value) && (*value)[0] != '\'')
|
if (!MathLib::isInt(value) && !MathLib::isFloat(value) && (value)[0] != '\'')
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1076,7 +1076,7 @@ static std::string conditionString(const Token * tok)
|
||||||
bool not_;
|
bool not_;
|
||||||
std::string op, value;
|
std::string op, value;
|
||||||
const Token *expr;
|
const Token *expr;
|
||||||
if (parseComparison(tok, ¬_, &op, &value, &expr, &inconclusive) && expr->isName()) {
|
if (parseComparison(tok, not_, op, value, expr, inconclusive) && expr->isName()) {
|
||||||
return conditionString(not_, expr, op, value);
|
return conditionString(not_, expr, op, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1192,13 +1192,13 @@ void CheckCondition::checkIncorrectLogicOperator()
|
||||||
bool not1;
|
bool not1;
|
||||||
std::string op1, value1;
|
std::string op1, value1;
|
||||||
const Token *expr1 = nullptr;
|
const Token *expr1 = nullptr;
|
||||||
parseable &= (parseComparison(comp1, ¬1, &op1, &value1, &expr1, &inconclusive));
|
parseable &= (parseComparison(comp1, not1, op1, value1, expr1, inconclusive));
|
||||||
|
|
||||||
// Parse RHS
|
// Parse RHS
|
||||||
bool not2;
|
bool not2;
|
||||||
std::string op2, value2;
|
std::string op2, value2;
|
||||||
const Token *expr2 = nullptr;
|
const Token *expr2 = nullptr;
|
||||||
parseable &= (parseComparison(comp2, ¬2, &op2, &value2, &expr2, &inconclusive));
|
parseable &= (parseComparison(comp2, not2, op2, value2, expr2, inconclusive));
|
||||||
|
|
||||||
if (inconclusive && !printInconclusive)
|
if (inconclusive && !printInconclusive)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -208,7 +208,7 @@ void CheckLeakAutoVar::check()
|
||||||
// Empty variable info
|
// Empty variable info
|
||||||
VarInfo varInfo;
|
VarInfo varInfo;
|
||||||
|
|
||||||
checkScope(scope->bodyStart, &varInfo, notzero, 0);
|
checkScope(scope->bodyStart, varInfo, notzero, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +287,7 @@ static const Token * isFunctionCall(const Token * nameToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
VarInfo *varInfo,
|
VarInfo &varInfo,
|
||||||
std::set<int> notzero,
|
std::set<int> notzero,
|
||||||
nonneg int recursiveCount)
|
nonneg int recursiveCount)
|
||||||
{
|
{
|
||||||
|
@ -299,9 +299,9 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
if (++recursiveCount > recursiveLimit) // maximum number of "else if ()"
|
if (++recursiveCount > recursiveLimit) // maximum number of "else if ()"
|
||||||
throw InternalError(startToken, "Internal limit: CheckLeakAutoVar::checkScope() Maximum recursive count of 1000 reached.", InternalError::LIMIT);
|
throw InternalError(startToken, "Internal limit: CheckLeakAutoVar::checkScope() Maximum recursive count of 1000 reached.", InternalError::LIMIT);
|
||||||
|
|
||||||
std::map<int, VarInfo::AllocInfo> &alloctype = varInfo->alloctype;
|
std::map<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype;
|
||||||
std::map<int, std::string> &possibleUsage = varInfo->possibleUsage;
|
std::map<int, std::string> &possibleUsage = varInfo.possibleUsage;
|
||||||
const std::set<int> conditionalAlloc(varInfo->conditionalAlloc);
|
const std::set<int> conditionalAlloc(varInfo.conditionalAlloc);
|
||||||
|
|
||||||
// Parse all tokens
|
// Parse all tokens
|
||||||
const Token * const endToken = startToken->link();
|
const Token * const endToken = startToken->link();
|
||||||
|
@ -372,7 +372,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
if (Token::Match(tokAssignOp, "= %var% [+;]")) {
|
if (Token::Match(tokAssignOp, "= %var% [+;]")) {
|
||||||
if (varTok->tokAt(2)->varId() != varTok->varId()) {
|
if (varTok->tokAt(2)->varId() != varTok->varId()) {
|
||||||
// If variable points at allocated memory => error
|
// If variable points at allocated memory => error
|
||||||
leakIfAllocated(varTok, *varInfo);
|
leakIfAllocated(varTok, varInfo);
|
||||||
|
|
||||||
// no multivariable checking currently => bail out for rhs variables
|
// no multivariable checking currently => bail out for rhs variables
|
||||||
for (const Token *tok2 = varTok; tok2; tok2 = tok2->next()) {
|
for (const Token *tok2 = varTok; tok2; tok2 = tok2->next()) {
|
||||||
|
@ -380,7 +380,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (tok2->varId()) {
|
if (tok2->varId()) {
|
||||||
varInfo->erase(tok2->varId());
|
varInfo.erase(tok2->varId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,8 +397,8 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
|
|
||||||
// Variable has already been allocated => error
|
// Variable has already been allocated => error
|
||||||
if (conditionalAlloc.find(varTok->varId()) == conditionalAlloc.end())
|
if (conditionalAlloc.find(varTok->varId()) == conditionalAlloc.end())
|
||||||
leakIfAllocated(varTok, *varInfo);
|
leakIfAllocated(varTok, varInfo);
|
||||||
varInfo->erase(varTok->varId());
|
varInfo.erase(varTok->varId());
|
||||||
|
|
||||||
if (!isLocalVarNoAutoDealloc(varTok, mTokenizer->isCPP()))
|
if (!isLocalVarNoAutoDealloc(varTok, mTokenizer->isCPP()))
|
||||||
continue;
|
continue;
|
||||||
|
@ -488,8 +488,8 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::simpleMatch(closingParenthesis, ") {")) {
|
if (Token::simpleMatch(closingParenthesis, ") {")) {
|
||||||
VarInfo varInfo1(*varInfo); // VarInfo for if code
|
VarInfo varInfo1(varInfo); // VarInfo for if code
|
||||||
VarInfo varInfo2(*varInfo); // VarInfo for else code
|
VarInfo varInfo2(varInfo); // VarInfo for else code
|
||||||
|
|
||||||
// Skip expressions before commas
|
// Skip expressions before commas
|
||||||
const Token * astOperand2AfterCommas = tok->next()->astOperand2();
|
const Token * astOperand2AfterCommas = tok->next()->astOperand2();
|
||||||
|
@ -535,13 +535,13 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
return ChildrenToVisit::none;
|
return ChildrenToVisit::none;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!checkScope(closingParenthesis->next(), &varInfo1, notzero, recursiveCount)) {
|
if (!checkScope(closingParenthesis->next(), varInfo1, notzero, recursiveCount)) {
|
||||||
varInfo->clear();
|
varInfo.clear();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
closingParenthesis = closingParenthesis->linkAt(1);
|
closingParenthesis = closingParenthesis->linkAt(1);
|
||||||
if (Token::simpleMatch(closingParenthesis, "} else {")) {
|
if (Token::simpleMatch(closingParenthesis, "} else {")) {
|
||||||
if (!checkScope(closingParenthesis->tokAt(2), &varInfo2, notzero, recursiveCount))
|
if (!checkScope(closingParenthesis->tokAt(2), varInfo2, notzero, recursiveCount))
|
||||||
continue;
|
continue;
|
||||||
tok = closingParenthesis->linkAt(2)->previous();
|
tok = closingParenthesis->linkAt(2)->previous();
|
||||||
} else {
|
} else {
|
||||||
|
@ -549,7 +549,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
VarInfo old;
|
VarInfo old;
|
||||||
old.swap(*varInfo);
|
old.swap(varInfo);
|
||||||
|
|
||||||
std::map<int, VarInfo::AllocInfo>::const_iterator it;
|
std::map<int, VarInfo::AllocInfo>::const_iterator it;
|
||||||
|
|
||||||
|
@ -568,7 +568,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
for (it = varInfo1.alloctype.cbegin(); it != varInfo1.alloctype.cend(); ++it) {
|
for (it = varInfo1.alloctype.cbegin(); it != varInfo1.alloctype.cend(); ++it) {
|
||||||
if (varInfo2.alloctype.find(it->first) == varInfo2.alloctype.end() &&
|
if (varInfo2.alloctype.find(it->first) == varInfo2.alloctype.end() &&
|
||||||
old.alloctype.find(it->first) == old.alloctype.end()) {
|
old.alloctype.find(it->first) == old.alloctype.end()) {
|
||||||
varInfo->conditionalAlloc.insert(it->first);
|
varInfo.conditionalAlloc.insert(it->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,20 +576,20 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
for (it = varInfo2.alloctype.cbegin(); it != varInfo2.alloctype.cend(); ++it) {
|
for (it = varInfo2.alloctype.cbegin(); it != varInfo2.alloctype.cend(); ++it) {
|
||||||
if (varInfo1.alloctype.find(it->first) == varInfo1.alloctype.end() &&
|
if (varInfo1.alloctype.find(it->first) == varInfo1.alloctype.end() &&
|
||||||
old.alloctype.find(it->first) == old.alloctype.end()) {
|
old.alloctype.find(it->first) == old.alloctype.end()) {
|
||||||
varInfo->conditionalAlloc.insert(it->first);
|
varInfo.conditionalAlloc.insert(it->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conditional allocation/deallocation
|
// Conditional allocation/deallocation
|
||||||
for (it = varInfo1.alloctype.cbegin(); it != varInfo1.alloctype.cend(); ++it) {
|
for (it = varInfo1.alloctype.cbegin(); it != varInfo1.alloctype.cend(); ++it) {
|
||||||
if (it->second.managed() && conditionalAlloc.find(it->first) != conditionalAlloc.end()) {
|
if (it->second.managed() && conditionalAlloc.find(it->first) != conditionalAlloc.end()) {
|
||||||
varInfo->conditionalAlloc.erase(it->first);
|
varInfo.conditionalAlloc.erase(it->first);
|
||||||
varInfo2.erase(it->first);
|
varInfo2.erase(it->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (it = varInfo2.alloctype.cbegin(); it != varInfo2.alloctype.cend(); ++it) {
|
for (it = varInfo2.alloctype.cbegin(); it != varInfo2.alloctype.cend(); ++it) {
|
||||||
if (it->second.managed() && conditionalAlloc.find(it->first) != conditionalAlloc.end()) {
|
if (it->second.managed() && conditionalAlloc.find(it->first) != conditionalAlloc.end()) {
|
||||||
varInfo->conditionalAlloc.erase(it->first);
|
varInfo.conditionalAlloc.erase(it->first);
|
||||||
varInfo1.erase(it->first);
|
varInfo1.erase(it->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -604,14 +604,14 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
|
|
||||||
// unknown control.. (TODO: handle loops)
|
// unknown control.. (TODO: handle loops)
|
||||||
else if ((Token::Match(tok, "%type% (") && Token::simpleMatch(tok->linkAt(1), ") {")) || Token::simpleMatch(tok, "do {")) {
|
else if ((Token::Match(tok, "%type% (") && Token::simpleMatch(tok->linkAt(1), ") {")) || Token::simpleMatch(tok, "do {")) {
|
||||||
varInfo->clear();
|
varInfo.clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return
|
// return
|
||||||
else if (tok->str() == "return") {
|
else if (tok->str() == "return") {
|
||||||
ret(tok, *varInfo);
|
ret(tok, varInfo);
|
||||||
varInfo->clear();
|
varInfo.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw
|
// throw
|
||||||
|
@ -625,8 +625,8 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
}
|
}
|
||||||
// If the execution leaves the function then treat it as return
|
// If the execution leaves the function then treat it as return
|
||||||
if (!tryFound)
|
if (!tryFound)
|
||||||
ret(tok, *varInfo);
|
ret(tok, varInfo);
|
||||||
varInfo->clear();
|
varInfo.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete
|
// delete
|
||||||
|
@ -670,9 +670,9 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
bool unknown = false;
|
bool unknown = false;
|
||||||
if (mTokenizer->isScopeNoReturn(tok->tokAt(2), &unknown)) {
|
if (mTokenizer->isScopeNoReturn(tok->tokAt(2), &unknown)) {
|
||||||
if (!unknown)
|
if (!unknown)
|
||||||
varInfo->clear();
|
varInfo.clear();
|
||||||
else if (!mSettings->library.isLeakIgnore(functionName) && !mSettings->library.isUse(functionName))
|
else if (!mSettings->library.isLeakIgnore(functionName) && !mSettings->library.isUse(functionName))
|
||||||
varInfo->possibleUsageAll(functionName);
|
varInfo.possibleUsageAll(functionName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,13 +681,13 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
|
|
||||||
// goto => weird execution path
|
// goto => weird execution path
|
||||||
else if (tok->str() == "goto") {
|
else if (tok->str() == "goto") {
|
||||||
varInfo->clear();
|
varInfo.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// continue/break
|
// continue/break
|
||||||
else if (Token::Match(tok, "continue|break ;")) {
|
else if (Token::Match(tok, "continue|break ;")) {
|
||||||
varInfo->clear();
|
varInfo.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check smart pointer
|
// Check smart pointer
|
||||||
|
@ -761,7 +761,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else { // there is a deleter, but we can't check it -> assume that it deallocates correctly
|
} else { // there is a deleter, but we can't check it -> assume that it deallocates correctly
|
||||||
varInfo->clear();
|
varInfo.clear();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -772,23 +772,23 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
changeAllocStatus(varInfo, allocation, vtok, vtok);
|
changeAllocStatus(varInfo, allocation, vtok, vtok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret(endToken, *varInfo, true);
|
ret(endToken, varInfo, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const tok, VarInfo *varInfo)
|
const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo)
|
||||||
{
|
{
|
||||||
// Deallocation and then dereferencing pointer..
|
// Deallocation and then dereferencing pointer..
|
||||||
if (tok->varId() > 0) {
|
if (tok->varId() > 0) {
|
||||||
// TODO : Write a separate checker for this that uses valueFlowForward.
|
// TODO : Write a separate checker for this that uses valueFlowForward.
|
||||||
const std::map<int, VarInfo::AllocInfo>::const_iterator var = varInfo->alloctype.find(tok->varId());
|
const std::map<int, VarInfo::AllocInfo>::const_iterator var = varInfo.alloctype.find(tok->varId());
|
||||||
if (var != varInfo->alloctype.end()) {
|
if (var != varInfo.alloctype.end()) {
|
||||||
bool unknown = false;
|
bool unknown = false;
|
||||||
if (var->second.status == VarInfo::DEALLOC && CheckNullPointer::isPointerDeRef(tok, unknown, mSettings) && !unknown) {
|
if (var->second.status == VarInfo::DEALLOC && CheckNullPointer::isPointerDeRef(tok, unknown, mSettings) && !unknown) {
|
||||||
deallocUseError(tok, tok->str());
|
deallocUseError(tok, tok->str());
|
||||||
} else if (Token::simpleMatch(tok->tokAt(-2), "= &")) {
|
} else if (Token::simpleMatch(tok->tokAt(-2), "= &")) {
|
||||||
varInfo->erase(tok->varId());
|
varInfo.erase(tok->varId());
|
||||||
} else {
|
} else {
|
||||||
// check if tok is assigned into another variable
|
// check if tok is assigned into another variable
|
||||||
const Token *rhs = tok;
|
const Token *rhs = tok;
|
||||||
|
@ -802,7 +802,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
|
||||||
}
|
}
|
||||||
if (rhs->varId() == tok->varId()) {
|
if (rhs->varId() == tok->varId()) {
|
||||||
// simple assignment
|
// simple assignment
|
||||||
varInfo->erase(tok->varId());
|
varInfo.erase(tok->varId());
|
||||||
} else if (rhs->str() == "(" && !mSettings->library.returnValue(rhs->astOperand1()).empty()) {
|
} else if (rhs->str() == "(" && !mSettings->library.returnValue(rhs->astOperand1()).empty()) {
|
||||||
// #9298, assignment through return value of a function
|
// #9298, assignment through return value of a function
|
||||||
const std::string &returnValue = mSettings->library.returnValue(rhs->astOperand1());
|
const std::string &returnValue = mSettings->library.returnValue(rhs->astOperand1());
|
||||||
|
@ -812,14 +812,14 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
|
||||||
if (func) {
|
if (func) {
|
||||||
const std::string arg = "arg" + std::to_string(argn + 1);
|
const std::string arg = "arg" + std::to_string(argn + 1);
|
||||||
if (returnValue == arg) {
|
if (returnValue == arg) {
|
||||||
varInfo->erase(tok->varId());
|
varInfo.erase(tok->varId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (Token::Match(tok->previous(), "& %name% = %var% ;")) {
|
} else if (Token::Match(tok->previous(), "& %name% = %var% ;")) {
|
||||||
varInfo->referenced.insert(tok->tokAt(2)->varId());
|
varInfo.referenced.insert(tok->tokAt(2)->varId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,23 +863,23 @@ void CheckLeakAutoVar::changeAllocStatusIfRealloc(std::map<int, VarInfo::AllocIn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CheckLeakAutoVar::changeAllocStatus(VarInfo *varInfo, const VarInfo::AllocInfo& allocation, const Token* tok, const Token* arg)
|
void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Token* tok, const Token* arg)
|
||||||
{
|
{
|
||||||
std::map<int, VarInfo::AllocInfo> &alloctype = varInfo->alloctype;
|
std::map<int, VarInfo::AllocInfo> &alloctype = varInfo.alloctype;
|
||||||
const std::map<int, VarInfo::AllocInfo>::iterator var = alloctype.find(arg->varId());
|
const std::map<int, VarInfo::AllocInfo>::iterator var = alloctype.find(arg->varId());
|
||||||
if (var != alloctype.end()) {
|
if (var != alloctype.end()) {
|
||||||
if (allocation.status == VarInfo::NOALLOC) {
|
if (allocation.status == VarInfo::NOALLOC) {
|
||||||
// possible usage
|
// possible usage
|
||||||
varInfo->possibleUsage[arg->varId()] = tok->str();
|
varInfo.possibleUsage[arg->varId()] = tok->str();
|
||||||
if (var->second.status == VarInfo::DEALLOC && arg->previous()->str() == "&")
|
if (var->second.status == VarInfo::DEALLOC && arg->previous()->str() == "&")
|
||||||
varInfo->erase(arg->varId());
|
varInfo.erase(arg->varId());
|
||||||
} else if (var->second.managed()) {
|
} else if (var->second.managed()) {
|
||||||
doubleFreeError(tok, var->second.allocTok, arg->str(), allocation.type);
|
doubleFreeError(tok, var->second.allocTok, arg->str(), allocation.type);
|
||||||
var->second.status = allocation.status;
|
var->second.status = allocation.status;
|
||||||
} else if (var->second.type != allocation.type && var->second.type != 0) {
|
} else if (var->second.type != allocation.type && var->second.type != 0) {
|
||||||
// mismatching allocation and deallocation
|
// mismatching allocation and deallocation
|
||||||
mismatchError(tok, var->second.allocTok, arg->str());
|
mismatchError(tok, var->second.allocTok, arg->str());
|
||||||
varInfo->erase(arg->varId());
|
varInfo.erase(arg->varId());
|
||||||
} else {
|
} else {
|
||||||
// deallocation
|
// deallocation
|
||||||
var->second.status = allocation.status;
|
var->second.status = allocation.status;
|
||||||
|
@ -892,7 +892,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo *varInfo, const VarInfo::AllocI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo *varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af)
|
void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af)
|
||||||
{
|
{
|
||||||
// Ignore function call?
|
// Ignore function call?
|
||||||
if (mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName)))
|
if (mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName)))
|
||||||
|
|
|
@ -126,7 +126,7 @@ private:
|
||||||
|
|
||||||
/** check for leaks in a function scope */
|
/** check for leaks in a function scope */
|
||||||
bool checkScope(const Token * const startToken,
|
bool checkScope(const Token * const startToken,
|
||||||
VarInfo *varInfo,
|
VarInfo &varInfo,
|
||||||
std::set<int> notzero,
|
std::set<int> notzero,
|
||||||
nonneg int recursiveCount);
|
nonneg int recursiveCount);
|
||||||
|
|
||||||
|
@ -135,13 +135,13 @@ private:
|
||||||
* @param varInfo Variable info
|
* @param varInfo Variable info
|
||||||
* @return next token to process (if no other checks needed for this token). NULL if other checks could be performed.
|
* @return next token to process (if no other checks needed for this token). NULL if other checks could be performed.
|
||||||
*/
|
*/
|
||||||
const Token * checkTokenInsideExpression(const Token * const tok, VarInfo *varInfo);
|
const Token * checkTokenInsideExpression(const Token * const tok, VarInfo &varInfo);
|
||||||
|
|
||||||
/** parse function call */
|
/** parse function call */
|
||||||
void functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo *varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af);
|
void functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af);
|
||||||
|
|
||||||
/** parse changes in allocation status */
|
/** parse changes in allocation status */
|
||||||
void changeAllocStatus(VarInfo *varInfo, const VarInfo::AllocInfo& allocation, const Token* tok, const Token* arg);
|
void changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Token* tok, const Token* arg);
|
||||||
|
|
||||||
/** update allocation status if reallocation function */
|
/** update allocation status if reallocation function */
|
||||||
void changeAllocStatusIfRealloc(std::map<int, VarInfo::AllocInfo> &alloctype, const Token *fTok, const Token *retTok);
|
void changeAllocStatusIfRealloc(std::map<int, VarInfo::AllocInfo> &alloctype, const Token *fTok, const Token *retTok);
|
||||||
|
|
|
@ -728,6 +728,8 @@ void CheckMemoryLeakStructMember::check()
|
||||||
|
|
||||||
bool CheckMemoryLeakStructMember::isMalloc(const Variable *variable)
|
bool CheckMemoryLeakStructMember::isMalloc(const Variable *variable)
|
||||||
{
|
{
|
||||||
|
if (!variable)
|
||||||
|
return false;
|
||||||
const int declarationId(variable->declarationId());
|
const int declarationId(variable->declarationId());
|
||||||
bool alloc = false;
|
bool alloc = false;
|
||||||
for (const Token *tok2 = variable->nameToken(); tok2 && tok2 != variable->scope()->bodyEnd; tok2 = tok2->next()) {
|
for (const Token *tok2 = variable->nameToken(); tok2 && tok2 != variable->scope()->bodyEnd; tok2 = tok2->next()) {
|
||||||
|
@ -742,6 +744,8 @@ bool CheckMemoryLeakStructMember::isMalloc(const Variable *variable)
|
||||||
|
|
||||||
void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const variable)
|
void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const variable)
|
||||||
{
|
{
|
||||||
|
if (!variable)
|
||||||
|
return;
|
||||||
// Is struct variable a pointer?
|
// Is struct variable a pointer?
|
||||||
if (variable->isArrayOrPointer()) {
|
if (variable->isArrayOrPointer()) {
|
||||||
// Check that variable is allocated with malloc
|
// Check that variable is allocated with malloc
|
||||||
|
|
|
@ -387,22 +387,19 @@ void CheckType::checkFloatToIntegerOverflow()
|
||||||
{
|
{
|
||||||
for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
const ValueType *vtint, *vtfloat;
|
const ValueType *vtint, *vtfloat;
|
||||||
const std::list<ValueFlow::Value> *floatValues;
|
|
||||||
|
|
||||||
// Explicit cast
|
// Explicit cast
|
||||||
if (Token::Match(tok, "( %name%") && tok->astOperand1() && !tok->astOperand2()) {
|
if (Token::Match(tok, "( %name%") && tok->astOperand1() && !tok->astOperand2()) {
|
||||||
vtint = tok->valueType();
|
vtint = tok->valueType();
|
||||||
vtfloat = tok->astOperand1()->valueType();
|
vtfloat = tok->astOperand1()->valueType();
|
||||||
floatValues = &tok->astOperand1()->values();
|
checkFloatToIntegerOverflow(tok, vtint, vtfloat, tok->astOperand1()->values());
|
||||||
checkFloatToIntegerOverflow(tok, vtint, vtfloat, floatValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assignment
|
// Assignment
|
||||||
else if (tok->str() == "=" && tok->astOperand1() && tok->astOperand2()) {
|
else if (tok->str() == "=" && tok->astOperand1() && tok->astOperand2()) {
|
||||||
vtint = tok->astOperand1()->valueType();
|
vtint = tok->astOperand1()->valueType();
|
||||||
vtfloat = tok->astOperand2()->valueType();
|
vtfloat = tok->astOperand2()->valueType();
|
||||||
floatValues = &tok->astOperand2()->values();
|
checkFloatToIntegerOverflow(tok, vtint, vtfloat, tok->astOperand2()->values());
|
||||||
checkFloatToIntegerOverflow(tok, vtint, vtfloat, floatValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (tok->str() == "return" && tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isFloat()) {
|
else if (tok->str() == "return" && tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isFloat()) {
|
||||||
|
@ -412,14 +409,13 @@ void CheckType::checkFloatToIntegerOverflow()
|
||||||
if (scope && scope->type == Scope::ScopeType::eFunction && scope->function && scope->function->retDef) {
|
if (scope && scope->type == Scope::ScopeType::eFunction && scope->function && scope->function->retDef) {
|
||||||
const ValueType &valueType = ValueType::parseDecl(scope->function->retDef, mSettings, mTokenizer->isCPP());
|
const ValueType &valueType = ValueType::parseDecl(scope->function->retDef, mSettings, mTokenizer->isCPP());
|
||||||
vtfloat = tok->astOperand1()->valueType();
|
vtfloat = tok->astOperand1()->valueType();
|
||||||
floatValues = &tok->astOperand1()->values();
|
checkFloatToIntegerOverflow(tok, &valueType, vtfloat, tok->astOperand1()->values());
|
||||||
checkFloatToIntegerOverflow(tok, &valueType, vtfloat, floatValues);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckType::checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list<ValueFlow::Value> *floatValues)
|
void CheckType::checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list<ValueFlow::Value> &floatValues)
|
||||||
{
|
{
|
||||||
// Conversion of float to integer?
|
// Conversion of float to integer?
|
||||||
if (!vtint || !vtint->isIntegral())
|
if (!vtint || !vtint->isIntegral())
|
||||||
|
@ -427,7 +423,7 @@ void CheckType::checkFloatToIntegerOverflow(const Token *tok, const ValueType *v
|
||||||
if (!vtfloat || !vtfloat->isFloat())
|
if (!vtfloat || !vtfloat->isFloat())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const ValueFlow::Value &f : *floatValues) {
|
for (const ValueFlow::Value &f : floatValues) {
|
||||||
if (f.valueType != ValueFlow::Value::ValueType::FLOAT)
|
if (f.valueType != ValueFlow::Value::ValueType::FLOAT)
|
||||||
continue;
|
continue;
|
||||||
if (!mSettings->isEnabled(&f, false))
|
if (!mSettings->isEnabled(&f, false))
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
|
|
||||||
/** @brief %Check for float to integer overflow */
|
/** @brief %Check for float to integer overflow */
|
||||||
void checkFloatToIntegerOverflow();
|
void checkFloatToIntegerOverflow();
|
||||||
void checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list<ValueFlow::Value> *floatValues);
|
void checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list<ValueFlow::Value> &floatValues);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -317,7 +317,7 @@ static std::string executeAddon(const AddonInfo &addonInfo,
|
||||||
const std::string &defaultPythonExe,
|
const std::string &defaultPythonExe,
|
||||||
const std::string &file,
|
const std::string &file,
|
||||||
const std::string &premiumArgs,
|
const std::string &premiumArgs,
|
||||||
const std::function<bool(std::string,std::vector<std::string>,std::string,std::string*)> &executeCommand)
|
const std::function<bool(std::string,std::vector<std::string>,std::string,std::string&)> &executeCommand)
|
||||||
{
|
{
|
||||||
const std::string redirect = "2>&1";
|
const std::string redirect = "2>&1";
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ static std::string executeAddon(const AddonInfo &addonInfo,
|
||||||
#endif
|
#endif
|
||||||
for (const char* py_exe : py_exes) {
|
for (const char* py_exe : py_exes) {
|
||||||
std::string out;
|
std::string out;
|
||||||
if (executeCommand(py_exe, split("--version"), redirect, &out) && out.compare(0, 7, "Python ") == 0 && std::isdigit(out[7])) {
|
if (executeCommand(py_exe, split("--version"), redirect, out) && out.compare(0, 7, "Python ") == 0 && std::isdigit(out[7])) {
|
||||||
pythonExe = py_exe;
|
pythonExe = py_exe;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -357,7 +357,7 @@ static std::string executeAddon(const AddonInfo &addonInfo,
|
||||||
args += fileArg;
|
args += fileArg;
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
if (!executeCommand(pythonExe, split(args), redirect, &result)) {
|
if (!executeCommand(pythonExe, split(args), redirect, result)) {
|
||||||
std::string message("Failed to execute addon (command: '" + pythonExe + " " + args + "'). Exitcode is nonzero.");
|
std::string message("Failed to execute addon (command: '" + pythonExe + " " + args + "'). Exitcode is nonzero.");
|
||||||
if (result.size() > 2) {
|
if (result.size() > 2) {
|
||||||
message = message + "\n" + message + "\nOutput:\n" + result;
|
message = message + "\n" + message + "\nOutput:\n" + result;
|
||||||
|
@ -390,7 +390,7 @@ static std::string getDefinesFlags(const std::string &semicolonSeparatedString)
|
||||||
|
|
||||||
CppCheck::CppCheck(ErrorLogger &errorLogger,
|
CppCheck::CppCheck(ErrorLogger &errorLogger,
|
||||||
bool useGlobalSuppressions,
|
bool useGlobalSuppressions,
|
||||||
std::function<bool(std::string,std::vector<std::string>,std::string,std::string*)> executeCommand)
|
std::function<bool(std::string,std::vector<std::string>,std::string,std::string&)> executeCommand)
|
||||||
: mErrorLogger(errorLogger)
|
: mErrorLogger(errorLogger)
|
||||||
, mExitCode(0)
|
, mExitCode(0)
|
||||||
, mUseGlobalSuppressions(useGlobalSuppressions)
|
, mUseGlobalSuppressions(useGlobalSuppressions)
|
||||||
|
@ -423,7 +423,7 @@ const char * CppCheck::extraVersion()
|
||||||
return ExtraVersion;
|
return ExtraVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool reportClangErrors(std::istream &is, const std::function<void(const ErrorMessage&)>& reportErr, std::vector<ErrorMessage> *warnings)
|
static bool reportClangErrors(std::istream &is, const std::function<void(const ErrorMessage&)>& reportErr, std::vector<ErrorMessage> &warnings)
|
||||||
{
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(is, line)) {
|
while (std::getline(is, line)) {
|
||||||
|
@ -433,7 +433,7 @@ static bool reportClangErrors(std::istream &is, const std::function<void(const E
|
||||||
std::string::size_type pos3 = line.find(": error: ");
|
std::string::size_type pos3 = line.find(": error: ");
|
||||||
if (pos3 == std::string::npos)
|
if (pos3 == std::string::npos)
|
||||||
pos3 = line.find(": fatal error:");
|
pos3 = line.find(": fatal error:");
|
||||||
if (warnings && pos3 == std::string::npos)
|
if (pos3 == std::string::npos)
|
||||||
pos3 = line.find(": warning:");
|
pos3 = line.find(": warning:");
|
||||||
if (pos3 == std::string::npos)
|
if (pos3 == std::string::npos)
|
||||||
continue;
|
continue;
|
||||||
|
@ -463,7 +463,7 @@ static bool reportClangErrors(std::istream &is, const std::function<void(const E
|
||||||
Certainty::normal);
|
Certainty::normal);
|
||||||
|
|
||||||
if (line.compare(pos3, 10, ": warning:") == 0) {
|
if (line.compare(pos3, 10, ": warning:") == 0) {
|
||||||
warnings->push_back(std::move(errmsg));
|
warnings.push_back(std::move(errmsg));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,7 +512,7 @@ unsigned int CppCheck::check(const std::string &path)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string output2;
|
std::string output2;
|
||||||
if (!mExecuteCommand(exe,split(args2),redirect2,&output2) || output2.find("TranslationUnitDecl") == std::string::npos) {
|
if (!mExecuteCommand(exe,split(args2),redirect2,output2) || output2.find("TranslationUnitDecl") == std::string::npos) {
|
||||||
std::cerr << "Failed to execute '" << exe << " " << args2 << " " << redirect2 << "'" << std::endl;
|
std::cerr << "Failed to execute '" << exe << " " << args2 << " " << redirect2 << "'" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -524,14 +524,14 @@ unsigned int CppCheck::check(const std::string &path)
|
||||||
auto reportError = [this](const ErrorMessage& errorMessage) {
|
auto reportError = [this](const ErrorMessage& errorMessage) {
|
||||||
reportErr(errorMessage);
|
reportErr(errorMessage);
|
||||||
};
|
};
|
||||||
if (reportClangErrors(fin, reportError, &compilerWarnings))
|
if (reportClangErrors(fin, reportError, compilerWarnings))
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
std::istringstream istr(output2);
|
std::istringstream istr(output2);
|
||||||
auto reportError = [this](const ErrorMessage& errorMessage) {
|
auto reportError = [this](const ErrorMessage& errorMessage) {
|
||||||
reportErr(errorMessage);
|
reportErr(errorMessage);
|
||||||
};
|
};
|
||||||
if (reportClangErrors(istr, reportError, &compilerWarnings))
|
if (reportClangErrors(istr, reportError, compilerWarnings))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,7 +762,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
|
||||||
// Calculate hash so it can be compared with old hash / future hashes
|
// Calculate hash so it can be compared with old hash / future hashes
|
||||||
const std::size_t hash = preprocessor.calculateHash(tokens1, toolinfo.str());
|
const std::size_t hash = preprocessor.calculateHash(tokens1, toolinfo.str());
|
||||||
std::list<ErrorMessage> errors;
|
std::list<ErrorMessage> errors;
|
||||||
if (!mAnalyzerInformation.analyzeFile(mSettings.buildDir, filename, cfgname, hash, &errors)) {
|
if (!mAnalyzerInformation.analyzeFile(mSettings.buildDir, filename, cfgname, hash, errors)) {
|
||||||
while (!errors.empty()) {
|
while (!errors.empty()) {
|
||||||
reportErr(errors.front());
|
reportErr(errors.front());
|
||||||
errors.pop_front();
|
errors.pop_front();
|
||||||
|
@ -1699,7 +1699,7 @@ void CppCheck::analyseClangTidy(const ImportProject::FileSettings &fileSettings)
|
||||||
|
|
||||||
const std::string args = "-quiet -checks=*,-clang-analyzer-*,-llvm* \"" + fileSettings.filename + "\" -- " + allIncludes + allDefines;
|
const std::string args = "-quiet -checks=*,-clang-analyzer-*,-llvm* \"" + fileSettings.filename + "\" -- " + allIncludes + allDefines;
|
||||||
std::string output;
|
std::string output;
|
||||||
if (!mExecuteCommand(exe, split(args), emptyString, &output)) {
|
if (!mExecuteCommand(exe, split(args), emptyString, output)) {
|
||||||
std::cerr << "Failed to execute '" << exe << "'" << std::endl;
|
std::cerr << "Failed to execute '" << exe << "'" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
*/
|
*/
|
||||||
CppCheck(ErrorLogger &errorLogger,
|
CppCheck(ErrorLogger &errorLogger,
|
||||||
bool useGlobalSuppressions,
|
bool useGlobalSuppressions,
|
||||||
std::function<bool(std::string,std::vector<std::string>,std::string,std::string*)> executeCommand);
|
std::function<bool(std::string,std::vector<std::string>,std::string,std::string&)> executeCommand);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructor.
|
* @brief Destructor.
|
||||||
|
@ -240,7 +240,7 @@ private:
|
||||||
AnalyzerInformation mAnalyzerInformation;
|
AnalyzerInformation mAnalyzerInformation;
|
||||||
|
|
||||||
/** Callback for executing a shell command (exe, args, output) */
|
/** Callback for executing a shell command (exe, args, output) */
|
||||||
std::function<bool(std::string,std::vector<std::string>,std::string,std::string*)> mExecuteCommand;
|
std::function<bool(std::string,std::vector<std::string>,std::string,std::string&)> mExecuteCommand;
|
||||||
|
|
||||||
std::ofstream mPlistFile;
|
std::ofstream mPlistFile;
|
||||||
};
|
};
|
||||||
|
|
|
@ -626,7 +626,7 @@ static std::list<std::string> toStringList(const std::string &s)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void importPropertyGroup(const tinyxml2::XMLElement *node, std::map<std::string,std::string,cppcheck::stricmp> *variables, std::string *includePath, bool *useOfMfc)
|
static void importPropertyGroup(const tinyxml2::XMLElement *node, std::map<std::string,std::string,cppcheck::stricmp> &variables, std::string &includePath, bool *useOfMfc)
|
||||||
{
|
{
|
||||||
if (useOfMfc) {
|
if (useOfMfc) {
|
||||||
for (const tinyxml2::XMLElement *e = node->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
for (const tinyxml2::XMLElement *e = node->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
||||||
|
@ -642,7 +642,7 @@ static void importPropertyGroup(const tinyxml2::XMLElement *node, std::map<std::
|
||||||
for (const tinyxml2::XMLElement *propertyGroup = node->FirstChildElement(); propertyGroup; propertyGroup = propertyGroup->NextSiblingElement()) {
|
for (const tinyxml2::XMLElement *propertyGroup = node->FirstChildElement(); propertyGroup; propertyGroup = propertyGroup->NextSiblingElement()) {
|
||||||
const std::string name(propertyGroup->Name());
|
const std::string name(propertyGroup->Name());
|
||||||
const char *text = propertyGroup->GetText();
|
const char *text = propertyGroup->GetText();
|
||||||
(*variables)[name] = std::string(text ? text : "");
|
variables[name] = std::string(text ? text : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!labelAttribute) {
|
} else if (!labelAttribute) {
|
||||||
|
@ -655,22 +655,22 @@ static void importPropertyGroup(const tinyxml2::XMLElement *node, std::map<std::
|
||||||
std::string path(text);
|
std::string path(text);
|
||||||
const std::string::size_type pos = path.find("$(IncludePath)");
|
const std::string::size_type pos = path.find("$(IncludePath)");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
path.replace(pos, 14U, *includePath);
|
path.replace(pos, 14U, includePath);
|
||||||
*includePath = path;
|
includePath = path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadVisualStudioProperties(const std::string &props, std::map<std::string,std::string,cppcheck::stricmp> *variables, std::string *includePath, const std::string &additionalIncludeDirectories, std::list<ItemDefinitionGroup> &itemDefinitionGroupList)
|
static void loadVisualStudioProperties(const std::string &props, std::map<std::string,std::string,cppcheck::stricmp> &variables, std::string &includePath, const std::string &additionalIncludeDirectories, std::list<ItemDefinitionGroup> &itemDefinitionGroupList)
|
||||||
{
|
{
|
||||||
std::string filename(props);
|
std::string filename(props);
|
||||||
// variables can't be resolved
|
// variables can't be resolved
|
||||||
if (!simplifyPathWithVariables(filename, *variables))
|
if (!simplifyPathWithVariables(filename, variables))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// prepend project dir (if it exists) to transform relative paths into absolute ones
|
// prepend project dir (if it exists) to transform relative paths into absolute ones
|
||||||
if (!Path::isAbsolute(filename) && variables->count("ProjectDir") > 0)
|
if (!Path::isAbsolute(filename) && variables.count("ProjectDir") > 0)
|
||||||
filename = Path::getAbsoluteFilePath(variables->at("ProjectDir") + filename);
|
filename = Path::getAbsoluteFilePath(variables.at("ProjectDir") + filename);
|
||||||
|
|
||||||
tinyxml2::XMLDocument doc;
|
tinyxml2::XMLDocument doc;
|
||||||
if (doc.LoadFile(filename.c_str()) != tinyxml2::XML_SUCCESS)
|
if (doc.LoadFile(filename.c_str()) != tinyxml2::XML_SUCCESS)
|
||||||
|
@ -750,7 +750,7 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map<std::str
|
||||||
} else if (std::strcmp(node->Name(), "ItemDefinitionGroup") == 0) {
|
} else if (std::strcmp(node->Name(), "ItemDefinitionGroup") == 0) {
|
||||||
itemDefinitionGroupList.emplace_back(node, additionalIncludeDirectories);
|
itemDefinitionGroupList.emplace_back(node, additionalIncludeDirectories);
|
||||||
} else if (std::strcmp(node->Name(), "PropertyGroup") == 0) {
|
} else if (std::strcmp(node->Name(), "PropertyGroup") == 0) {
|
||||||
importPropertyGroup(node, &variables, &includePath, &useOfMfc);
|
importPropertyGroup(node, variables, includePath, &useOfMfc);
|
||||||
} else if (std::strcmp(node->Name(), "ImportGroup") == 0) {
|
} else if (std::strcmp(node->Name(), "ImportGroup") == 0) {
|
||||||
const char *labelAttribute = node->Attribute("Label");
|
const char *labelAttribute = node->Attribute("Label");
|
||||||
if (labelAttribute && std::strcmp(labelAttribute, "PropertySheets") == 0) {
|
if (labelAttribute && std::strcmp(labelAttribute, "PropertySheets") == 0) {
|
||||||
|
@ -758,7 +758,7 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map<std::str
|
||||||
if (std::strcmp(e->Name(), "Import") == 0) {
|
if (std::strcmp(e->Name(), "Import") == 0) {
|
||||||
const char *projectAttribute = e->Attribute("Project");
|
const char *projectAttribute = e->Attribute("Project");
|
||||||
if (projectAttribute)
|
if (projectAttribute)
|
||||||
loadVisualStudioProperties(projectAttribute, &variables, &includePath, additionalIncludeDirectories, itemDefinitionGroupList);
|
loadVisualStudioProperties(projectAttribute, variables, includePath, additionalIncludeDirectories, itemDefinitionGroupList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -953,10 +953,10 @@ bool Library::isFloatArgValid(const Token *ftok, int argnr, double argvalue) con
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Library::getFunctionName(const Token *ftok, bool *error) const
|
std::string Library::getFunctionName(const Token *ftok, bool &error) const
|
||||||
{
|
{
|
||||||
if (!ftok) {
|
if (!ftok) {
|
||||||
*error = true;
|
error = true;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
if (ftok->isName()) {
|
if (ftok->isName()) {
|
||||||
|
@ -980,13 +980,13 @@ std::string Library::getFunctionName(const Token *ftok, bool *error) const
|
||||||
if (ftok->str() == "." && ftok->astOperand1()) {
|
if (ftok->str() == "." && ftok->astOperand1()) {
|
||||||
const std::string type = astCanonicalType(ftok->astOperand1());
|
const std::string type = astCanonicalType(ftok->astOperand1());
|
||||||
if (type.empty()) {
|
if (type.empty()) {
|
||||||
*error = true;
|
error = true;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return type + "::" + getFunctionName(ftok->astOperand2(),error);
|
return type + "::" + getFunctionName(ftok->astOperand2(),error);
|
||||||
}
|
}
|
||||||
*error = true;
|
error = true;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -999,7 +999,7 @@ std::string Library::getFunctionName(const Token *ftok) const
|
||||||
if (ftok->astParent()) {
|
if (ftok->astParent()) {
|
||||||
bool error = false;
|
bool error = false;
|
||||||
const Token * tok = ftok->astParent()->isUnaryOp("&") ? ftok->astParent()->astOperand1() : ftok->next()->astOperand1();
|
const Token * tok = ftok->astParent()->isUnaryOp("&") ? ftok->astParent()->astOperand1() : ftok->next()->astOperand1();
|
||||||
const std::string ret = getFunctionName(tok, &error);
|
const std::string ret = getFunctionName(tok, error);
|
||||||
return error ? std::string() : ret;
|
return error ? std::string() : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ public:
|
||||||
return ((id > 0) && ((id & 1) == 0));
|
return ((id > 0) && ((id & 1) == 0));
|
||||||
}
|
}
|
||||||
static bool ismemory(const AllocFunc* const func) {
|
static bool ismemory(const AllocFunc* const func) {
|
||||||
return ((func->groupId > 0) && ((func->groupId & 1) == 0));
|
return func && (func->groupId > 0) && ((func->groupId & 1) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** is allocation type resource? */
|
/** is allocation type resource? */
|
||||||
|
@ -162,7 +162,7 @@ public:
|
||||||
return ((id > 0) && ((id & 1) == 1));
|
return ((id > 0) && ((id & 1) == 1));
|
||||||
}
|
}
|
||||||
static bool isresource(const AllocFunc* const func) {
|
static bool isresource(const AllocFunc* const func) {
|
||||||
return ((func->groupId > 0) && ((func->groupId & 1) == 1));
|
return func && (func->groupId > 0) && ((func->groupId & 1) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool formatstr_function(const Token* ftok) const;
|
bool formatstr_function(const Token* ftok) const;
|
||||||
|
@ -652,7 +652,7 @@ private:
|
||||||
|
|
||||||
const ArgumentChecks * getarg(const Token *ftok, int argnr) const;
|
const ArgumentChecks * getarg(const Token *ftok, int argnr) const;
|
||||||
|
|
||||||
std::string getFunctionName(const Token *ftok, bool *error) const;
|
std::string getFunctionName(const Token *ftok, bool &error) const;
|
||||||
|
|
||||||
static const AllocFunc* getAllocDealloc(const std::map<std::string, AllocFunc> &data, const std::string &name) {
|
static const AllocFunc* getAllocDealloc(const std::map<std::string, AllocFunc> &data, const std::string &name) {
|
||||||
const std::map<std::string, AllocFunc>::const_iterator it = data.find(name);
|
const std::map<std::string, AllocFunc>::const_iterator it = data.find(name);
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std::list<Suppressions::Suppression> &inlineSuppressions, std::list<BadInlineSuppression> *bad)
|
static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std::list<Suppressions::Suppression> &inlineSuppressions, std::list<BadInlineSuppression> &bad)
|
||||||
{
|
{
|
||||||
const std::string cppchecksuppress("cppcheck-suppress");
|
const std::string cppchecksuppress("cppcheck-suppress");
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std:
|
||||||
std::vector<Suppressions::Suppression> suppressions = Suppressions::parseMultiSuppressComment(comment, &errmsg);
|
std::vector<Suppressions::Suppression> suppressions = Suppressions::parseMultiSuppressComment(comment, &errmsg);
|
||||||
|
|
||||||
if (!errmsg.empty())
|
if (!errmsg.empty())
|
||||||
bad->emplace_back(tok->location, std::move(errmsg));
|
bad.emplace_back(tok->location, std::move(errmsg));
|
||||||
|
|
||||||
std::copy_if(suppressions.cbegin(), suppressions.cend(), std::back_inserter(inlineSuppressions), [](const Suppressions::Suppression& s) {
|
std::copy_if(suppressions.cbegin(), suppressions.cend(), std::back_inserter(inlineSuppressions), [](const Suppressions::Suppression& s) {
|
||||||
return !s.errorId.empty();
|
return !s.errorId.empty();
|
||||||
|
@ -126,13 +126,13 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std:
|
||||||
inlineSuppressions.push_back(std::move(s));
|
inlineSuppressions.push_back(std::move(s));
|
||||||
|
|
||||||
if (!errmsg.empty())
|
if (!errmsg.empty())
|
||||||
bad->emplace_back(tok->location, std::move(errmsg));
|
bad.emplace_back(tok->location, std::move(errmsg));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addinlineSuppressions(const simplecpp::TokenList &tokens, Settings &mSettings, std::list<BadInlineSuppression> *bad)
|
static void addinlineSuppressions(const simplecpp::TokenList &tokens, Settings &mSettings, std::list<BadInlineSuppression> &bad)
|
||||||
{
|
{
|
||||||
for (const simplecpp::Token *tok = tokens.cfront(); tok; tok = tok->next) {
|
for (const simplecpp::Token *tok = tokens.cfront(); tok; tok = tok->next) {
|
||||||
if (!tok->comment)
|
if (!tok->comment)
|
||||||
|
@ -192,10 +192,10 @@ void Preprocessor::inlineSuppressions(const simplecpp::TokenList &tokens)
|
||||||
if (!mSettings.inlineSuppressions)
|
if (!mSettings.inlineSuppressions)
|
||||||
return;
|
return;
|
||||||
std::list<BadInlineSuppression> err;
|
std::list<BadInlineSuppression> err;
|
||||||
::addinlineSuppressions(tokens, mSettings, &err);
|
::addinlineSuppressions(tokens, mSettings, err);
|
||||||
for (std::map<std::string,simplecpp::TokenList*>::const_iterator it = mTokenLists.cbegin(); it != mTokenLists.cend(); ++it) {
|
for (std::map<std::string,simplecpp::TokenList*>::const_iterator it = mTokenLists.cbegin(); it != mTokenLists.cend(); ++it) {
|
||||||
if (it->second)
|
if (it->second)
|
||||||
::addinlineSuppressions(*it->second, mSettings, &err);
|
::addinlineSuppressions(*it->second, mSettings, err);
|
||||||
}
|
}
|
||||||
for (const BadInlineSuppression &bad : err) {
|
for (const BadInlineSuppression &bad : err) {
|
||||||
error(bad.location.file(), bad.location.line, bad.errmsg);
|
error(bad.location.file(), bad.location.line, bad.errmsg);
|
||||||
|
|
|
@ -58,7 +58,7 @@ void ProgramMemory::setValue(const Token* expr, const ValueFlow::Value& value) {
|
||||||
if (tok->hasKnownIntValue())
|
if (tok->hasKnownIntValue())
|
||||||
return {tok->values().front().intvalue};
|
return {tok->values().front().intvalue};
|
||||||
MathLib::bigint result = 0;
|
MathLib::bigint result = 0;
|
||||||
if (getIntValue(tok->exprId(), &result))
|
if (getIntValue(tok->exprId(), result))
|
||||||
return {result};
|
return {result};
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
@ -77,11 +77,11 @@ const ValueFlow::Value* ProgramMemory::getValue(nonneg int exprid, bool impossib
|
||||||
}
|
}
|
||||||
|
|
||||||
// cppcheck-suppress unusedFunction
|
// cppcheck-suppress unusedFunction
|
||||||
bool ProgramMemory::getIntValue(nonneg int exprid, MathLib::bigint* result) const
|
bool ProgramMemory::getIntValue(nonneg int exprid, MathLib::bigint& result) const
|
||||||
{
|
{
|
||||||
const ValueFlow::Value* value = getValue(exprid);
|
const ValueFlow::Value* value = getValue(exprid);
|
||||||
if (value && value->isIntValue()) {
|
if (value && value->isIntValue()) {
|
||||||
*result = value->intvalue;
|
result = value->intvalue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -106,25 +106,25 @@ bool ProgramMemory::getTokValue(nonneg int exprid, const Token** result) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// cppcheck-suppress unusedFunction
|
// cppcheck-suppress unusedFunction
|
||||||
bool ProgramMemory::getContainerSizeValue(nonneg int exprid, MathLib::bigint* result) const
|
bool ProgramMemory::getContainerSizeValue(nonneg int exprid, MathLib::bigint& result) const
|
||||||
{
|
{
|
||||||
const ValueFlow::Value* value = getValue(exprid);
|
const ValueFlow::Value* value = getValue(exprid);
|
||||||
if (value && value->isContainerSizeValue()) {
|
if (value && value->isContainerSizeValue()) {
|
||||||
*result = value->intvalue;
|
result = value->intvalue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool ProgramMemory::getContainerEmptyValue(nonneg int exprid, MathLib::bigint* result) const
|
bool ProgramMemory::getContainerEmptyValue(nonneg int exprid, MathLib::bigint& result) const
|
||||||
{
|
{
|
||||||
const ValueFlow::Value* value = getValue(exprid, true);
|
const ValueFlow::Value* value = getValue(exprid, true);
|
||||||
if (value && value->isContainerSizeValue()) {
|
if (value && value->isContainerSizeValue()) {
|
||||||
if (value->isImpossible() && value->intvalue == 0) {
|
if (value->isImpossible() && value->intvalue == 0) {
|
||||||
*result = false;
|
result = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!value->isImpossible()) {
|
if (!value->isImpossible()) {
|
||||||
*result = (value->intvalue == 0);
|
result = (value->intvalue == 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ static bool evaluateCondition(const std::string& op,
|
||||||
}
|
}
|
||||||
MathLib::bigint result = 0;
|
MathLib::bigint result = 0;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
execute(condition, &pm, &result, &error, settings);
|
execute(condition, pm, &result, &error, settings);
|
||||||
return !error && result == r;
|
return !error && result == r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Toke
|
||||||
return {t->values().front().intvalue};
|
return {t->values().front().intvalue};
|
||||||
MathLib::bigint result = 0;
|
MathLib::bigint result = 0;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
execute(t, &pm, &result, &error);
|
execute(t, pm, &result, &error);
|
||||||
if (!error)
|
if (!error)
|
||||||
return {result};
|
return {result};
|
||||||
return std::vector<MathLib::bigint>{};
|
return std::vector<MathLib::bigint>{};
|
||||||
|
@ -323,7 +323,7 @@ static void fillProgramMemoryFromConditions(ProgramMemory& pm, const Scope* scop
|
||||||
return;
|
return;
|
||||||
MathLib::bigint result = 0;
|
MathLib::bigint result = 0;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
execute(condTok, &pm, &result, &error);
|
execute(condTok, pm, &result, &error);
|
||||||
if (error)
|
if (error)
|
||||||
programMemoryParseCondition(pm, condTok, endTok, settings, scope->type != Scope::eElse);
|
programMemoryParseCondition(pm, condTok, endTok, settings, scope->type != Scope::eElse);
|
||||||
}
|
}
|
||||||
|
@ -719,7 +719,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::atan2(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::atan2(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -731,7 +731,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::remainder(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::remainder(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -743,7 +743,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::nextafter(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::nextafter(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -755,7 +755,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::nexttoward(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::nexttoward(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -767,7 +767,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::hypot(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::hypot(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -779,7 +779,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::fdim(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::fdim(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -791,7 +791,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::fmax(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::fmax(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -803,7 +803,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::fmin(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::fmin(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -815,7 +815,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::fmod(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::fmod(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -827,7 +827,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::pow(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::pow(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -839,7 +839,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::scalbln(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::scalbln(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -851,7 +851,7 @@ static std::unordered_map<std::string, BuiltinLibraryFunction> createBuiltinLibr
|
||||||
return ValueFlow::Value::unknown();
|
return ValueFlow::Value::unknown();
|
||||||
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
const double value = args[0].isFloatValue() ? args[0].floatValue : args[0].intvalue;
|
||||||
ValueFlow::Value v;
|
ValueFlow::Value v;
|
||||||
combineValueProperties(args[0], args[1], &v);
|
combineValueProperties(args[0], args[1], v);
|
||||||
v.floatValue = std::ldexp(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
v.floatValue = std::ldexp(value, args[1].isFloatValue() ? args[1].floatValue : args[1].intvalue);
|
||||||
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
v.valueType = ValueFlow::Value::ValueType::FLOAT;
|
||||||
return v;
|
return v;
|
||||||
|
@ -1408,12 +1408,12 @@ ValueFlow::Value evaluateLibraryFunction(const std::unordered_map<nonneg int, Va
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(const Token* expr,
|
void execute(const Token* expr,
|
||||||
ProgramMemory* const programMemory,
|
ProgramMemory& programMemory,
|
||||||
MathLib::bigint* result,
|
MathLib::bigint* result,
|
||||||
bool* error,
|
bool* error,
|
||||||
const Settings* settings)
|
const Settings* settings)
|
||||||
{
|
{
|
||||||
ValueFlow::Value v = execute(expr, *programMemory, settings);
|
ValueFlow::Value v = execute(expr, programMemory, settings);
|
||||||
if (!v.isIntValue() || v.isImpossible()) {
|
if (!v.isIntValue() || v.isImpossible()) {
|
||||||
if (error)
|
if (error)
|
||||||
*error = true;
|
*error = true;
|
||||||
|
|
|
@ -74,11 +74,11 @@ struct ProgramMemory {
|
||||||
void setValue(const Token* expr, const ValueFlow::Value& value);
|
void setValue(const Token* expr, const ValueFlow::Value& value);
|
||||||
const ValueFlow::Value* getValue(nonneg int exprid, bool impossible = false) const;
|
const ValueFlow::Value* getValue(nonneg int exprid, bool impossible = false) const;
|
||||||
|
|
||||||
bool getIntValue(nonneg int exprid, MathLib::bigint* result) const;
|
bool getIntValue(nonneg int exprid, MathLib::bigint& result) const;
|
||||||
void setIntValue(const Token* expr, MathLib::bigint value, bool impossible = false);
|
void setIntValue(const Token* expr, MathLib::bigint value, bool impossible = false);
|
||||||
|
|
||||||
bool getContainerSizeValue(nonneg int exprid, MathLib::bigint* result) const;
|
bool getContainerSizeValue(nonneg int exprid, MathLib::bigint& result) const;
|
||||||
bool getContainerEmptyValue(nonneg int exprid, MathLib::bigint* result) const;
|
bool getContainerEmptyValue(nonneg int exprid, MathLib::bigint& result) const;
|
||||||
void setContainerSizeValue(const Token* expr, MathLib::bigint value, bool isEqual = true);
|
void setContainerSizeValue(const Token* expr, MathLib::bigint value, bool isEqual = true);
|
||||||
|
|
||||||
void setUnknown(const Token* expr);
|
void setUnknown(const Token* expr);
|
||||||
|
@ -143,7 +143,7 @@ struct ProgramMemoryState {
|
||||||
};
|
};
|
||||||
|
|
||||||
void execute(const Token* expr,
|
void execute(const Token* expr,
|
||||||
ProgramMemory* const programMemory,
|
ProgramMemory& programMemory,
|
||||||
MathLib::bigint* result,
|
MathLib::bigint* result,
|
||||||
bool* error,
|
bool* error,
|
||||||
const Settings* settings = nullptr);
|
const Settings* settings = nullptr);
|
||||||
|
|
|
@ -2167,7 +2167,7 @@ void Variable::evaluate(const Settings* settings)
|
||||||
|
|
||||||
bool isContainer = false;
|
bool isContainer = false;
|
||||||
if (mNameToken)
|
if (mNameToken)
|
||||||
setFlag(fIsArray, arrayDimensions(settings, &isContainer));
|
setFlag(fIsArray, arrayDimensions(settings, isContainer));
|
||||||
|
|
||||||
if (mTypeStartToken)
|
if (mTypeStartToken)
|
||||||
setValueType(ValueType::parseDecl(mTypeStartToken,settings, true)); // TODO: set isCpp
|
setValueType(ValueType::parseDecl(mTypeStartToken,settings, true)); // TODO: set isCpp
|
||||||
|
@ -2238,7 +2238,7 @@ void Variable::evaluate(const Settings* settings)
|
||||||
tok = tok->link()->previous();
|
tok = tok->link()->previous();
|
||||||
// add array dimensions if present
|
// add array dimensions if present
|
||||||
if (tok && tok->next()->str() == "[")
|
if (tok && tok->next()->str() == "[")
|
||||||
setFlag(fIsArray, arrayDimensions(settings, &isContainer));
|
setFlag(fIsArray, arrayDimensions(settings, isContainer));
|
||||||
}
|
}
|
||||||
if (!tok)
|
if (!tok)
|
||||||
return;
|
return;
|
||||||
|
@ -3502,14 +3502,14 @@ bool Type::isDerivedFrom(const std::string & ancestor) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Variable::arrayDimensions(const Settings* settings, bool* isContainer)
|
bool Variable::arrayDimensions(const Settings* settings, bool& isContainer)
|
||||||
{
|
{
|
||||||
*isContainer = false;
|
isContainer = false;
|
||||||
const Library::Container* container = settings->library.detectContainer(mTypeStartToken);
|
const Library::Container* container = settings->library.detectContainer(mTypeStartToken);
|
||||||
if (container && container->arrayLike_indexOp && container->size_templateArgNo > 0) {
|
if (container && container->arrayLike_indexOp && container->size_templateArgNo > 0) {
|
||||||
const Token* tok = Token::findsimplematch(mTypeStartToken, "<");
|
const Token* tok = Token::findsimplematch(mTypeStartToken, "<");
|
||||||
if (tok) {
|
if (tok) {
|
||||||
*isContainer = true;
|
isContainer = true;
|
||||||
Dimension dimension_;
|
Dimension dimension_;
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
for (int i = 0; i < container->size_templateArgNo && tok; i++) {
|
for (int i = 0; i < container->size_templateArgNo && tok; i++) {
|
||||||
|
|
|
@ -226,7 +226,7 @@ class CPPCHECKLIB Variable {
|
||||||
* @param isContainer Is the array container-like?
|
* @param isContainer Is the array container-like?
|
||||||
* @return true if array, false if not
|
* @return true if array, false if not
|
||||||
*/
|
*/
|
||||||
bool arrayDimensions(const Settings* settings, bool* isContainer);
|
bool arrayDimensions(const Settings* settings, bool& isContainer);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Variable(const Token *name_, const Token *start_, const Token *end_,
|
Variable(const Token *name_, const Token *start_, const Token *end_,
|
||||||
|
|
|
@ -2496,13 +2496,13 @@ void TokenImpl::setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, M
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TokenImpl::getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint *value) const
|
bool TokenImpl::getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint &value) const
|
||||||
{
|
{
|
||||||
struct CppcheckAttributes *attr = mCppcheckAttributes;
|
struct CppcheckAttributes *attr = mCppcheckAttributes;
|
||||||
while (attr && attr->type != type)
|
while (attr && attr->type != type)
|
||||||
attr = attr->next;
|
attr = attr->next;
|
||||||
if (attr)
|
if (attr)
|
||||||
*value = attr->value;
|
value = attr->value;
|
||||||
return attr != nullptr;
|
return attr != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ struct TokenImpl {
|
||||||
TokenDebug mDebug;
|
TokenDebug mDebug;
|
||||||
|
|
||||||
void setCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint value);
|
void setCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint value);
|
||||||
bool getCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint *value) const;
|
bool getCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint &value) const;
|
||||||
|
|
||||||
TokenImpl()
|
TokenImpl()
|
||||||
: mVarId(0),
|
: mVarId(0),
|
||||||
|
@ -559,7 +559,7 @@ public:
|
||||||
void setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint value) {
|
void setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint value) {
|
||||||
mImpl->setCppcheckAttribute(type, value);
|
mImpl->setCppcheckAttribute(type, value);
|
||||||
}
|
}
|
||||||
bool getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint *value) const {
|
bool getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint &value) const {
|
||||||
return mImpl->getCppcheckAttribute(type, value);
|
return mImpl->getCppcheckAttribute(type, value);
|
||||||
}
|
}
|
||||||
bool hasCppcheckAttributes() const {
|
bool hasCppcheckAttributes() const {
|
||||||
|
|
|
@ -3483,8 +3483,11 @@ public:
|
||||||
const std::map<std::string, nonneg int>& map(bool global) const {
|
const std::map<std::string, nonneg int>& map(bool global) const {
|
||||||
return global ? mVariableId_global : mVariableId;
|
return global ? mVariableId_global : mVariableId;
|
||||||
}
|
}
|
||||||
nonneg int* getVarId() const {
|
nonneg int getVarId() const {
|
||||||
return &mVarId;
|
return mVarId;
|
||||||
|
}
|
||||||
|
nonneg int& getVarId() {
|
||||||
|
return mVarId;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3661,7 +3664,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const VariableMap& varia
|
||||||
|
|
||||||
void Tokenizer::setVarIdStructMembers(Token **tok1,
|
void Tokenizer::setVarIdStructMembers(Token **tok1,
|
||||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
||||||
nonneg int *varId) const
|
nonneg int &varId) const
|
||||||
{
|
{
|
||||||
Token *tok = *tok1;
|
Token *tok = *tok1;
|
||||||
|
|
||||||
|
@ -3680,8 +3683,8 @@ void Tokenizer::setVarIdStructMembers(Token **tok1,
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
const std::map<std::string, nonneg int>::iterator it = members.find(tok->str());
|
const std::map<std::string, nonneg int>::iterator it = members.find(tok->str());
|
||||||
if (it == members.end()) {
|
if (it == members.end()) {
|
||||||
members[tok->str()] = ++(*varId);
|
members[tok->str()] = ++varId;
|
||||||
tok->varId(*varId);
|
tok->varId(varId);
|
||||||
} else {
|
} else {
|
||||||
tok->varId(it->second);
|
tok->varId(it->second);
|
||||||
}
|
}
|
||||||
|
@ -3714,8 +3717,8 @@ void Tokenizer::setVarIdStructMembers(Token **tok1,
|
||||||
std::map<std::string, nonneg int>& members = structMembers[struct_varid];
|
std::map<std::string, nonneg int>& members = structMembers[struct_varid];
|
||||||
const std::map<std::string, nonneg int>::iterator it = members.find(tok->str());
|
const std::map<std::string, nonneg int>::iterator it = members.find(tok->str());
|
||||||
if (it == members.end()) {
|
if (it == members.end()) {
|
||||||
members[tok->str()] = ++(*varId);
|
members[tok->str()] = ++varId;
|
||||||
tok->varId(*varId);
|
tok->varId(varId);
|
||||||
} else {
|
} else {
|
||||||
tok->varId(it->second);
|
tok->varId(it->second);
|
||||||
}
|
}
|
||||||
|
@ -3726,7 +3729,7 @@ void Tokenizer::setVarIdStructMembers(Token **tok1,
|
||||||
|
|
||||||
|
|
||||||
void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
||||||
const VariableMap &variableMap,
|
VariableMap &variableMap,
|
||||||
const nonneg int scopeStartVarId,
|
const nonneg int scopeStartVarId,
|
||||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers)
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers)
|
||||||
{
|
{
|
||||||
|
@ -3808,7 +3811,7 @@ void Tokenizer::setVarIdClassFunction(const std::string &classname,
|
||||||
const Token * const endToken,
|
const Token * const endToken,
|
||||||
const std::map<std::string, nonneg int> &varlist,
|
const std::map<std::string, nonneg int> &varlist,
|
||||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
||||||
nonneg int *varId_)
|
nonneg int &varId_)
|
||||||
{
|
{
|
||||||
for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) {
|
for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) {
|
||||||
if (tok2->varId() != 0 || !tok2->isName())
|
if (tok2->varId() != 0 || !tok2->isName())
|
||||||
|
@ -3889,7 +3892,7 @@ void Tokenizer::setVarIdPass1()
|
||||||
if (!variableMap.leaveScope())
|
if (!variableMap.leaveScope())
|
||||||
cppcheckError(tok);
|
cppcheckError(tok);
|
||||||
} else if (tok->str() == "{") {
|
} else if (tok->str() == "{") {
|
||||||
scopeStack.emplace(true, scopeStack.top().isStructInit || tok->strAt(-1) == "=", /*isEnum=*/ false, *variableMap.getVarId());
|
scopeStack.emplace(true, scopeStack.top().isStructInit || tok->strAt(-1) == "=", /*isEnum=*/ false, variableMap.getVarId());
|
||||||
|
|
||||||
// check if this '{' is a start of an "if" body
|
// check if this '{' is a start of an "if" body
|
||||||
const Token * ifToken = tok->previous();
|
const Token * ifToken = tok->previous();
|
||||||
|
@ -3951,7 +3954,7 @@ void Tokenizer::setVarIdPass1()
|
||||||
variableMap.enterScope();
|
variableMap.enterScope();
|
||||||
}
|
}
|
||||||
initlist = false;
|
initlist = false;
|
||||||
scopeStack.emplace(isExecutable, scopeStack.top().isStructInit || tok->strAt(-1) == "=", isEnumStart(tok), *variableMap.getVarId());
|
scopeStack.emplace(isExecutable, scopeStack.top().isStructInit || tok->strAt(-1) == "=", isEnumStart(tok), variableMap.getVarId());
|
||||||
} else { /* if (tok->str() == "}") */
|
} else { /* if (tok->str() == "}") */
|
||||||
bool isNamespace = false;
|
bool isNamespace = false;
|
||||||
for (const Token *tok1 = tok->link()->previous(); tok1 && tok1->isName(); tok1 = tok1->previous()) {
|
for (const Token *tok1 = tok->link()->previous(); tok1 && tok1->isName(); tok1 = tok1->previous()) {
|
||||||
|
@ -4212,7 +4215,7 @@ void Tokenizer::setVarIdPass1()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mVarId = *variableMap.getVarId();
|
mVarId = variableMap.getVarId();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -4460,14 +4463,14 @@ void Tokenizer::setVarIdPass2()
|
||||||
if (tok2->str() == "(") {
|
if (tok2->str() == "(") {
|
||||||
Token *funcstart = const_cast<Token*>(isFunctionHead(tok2, "{"));
|
Token *funcstart = const_cast<Token*>(isFunctionHead(tok2, "{"));
|
||||||
if (funcstart) {
|
if (funcstart) {
|
||||||
setVarIdClassFunction(scopeName2 + classname, funcstart, funcstart->link(), thisClassVars, structMembers, &mVarId);
|
setVarIdClassFunction(scopeName2 + classname, funcstart, funcstart->link(), thisClassVars, structMembers, mVarId);
|
||||||
tok2 = funcstart->link();
|
tok2 = funcstart->link();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tok2->str() == "{") {
|
if (tok2->str() == "{") {
|
||||||
if (tok2->strAt(-1) == ")")
|
if (tok2->strAt(-1) == ")")
|
||||||
setVarIdClassFunction(scopeName2 + classname, tok2, tok2->link(), thisClassVars, structMembers, &mVarId);
|
setVarIdClassFunction(scopeName2 + classname, tok2, tok2->link(), thisClassVars, structMembers, mVarId);
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
} else if (Token::Match(tok2, "( %name%|)") && !Token::Match(tok2->link(), "(|[")) {
|
} else if (Token::Match(tok2, "( %name%|)") && !Token::Match(tok2->link(), "(|[")) {
|
||||||
tok2 = tok2->link();
|
tok2 = tok2->link();
|
||||||
|
@ -4513,7 +4516,7 @@ void Tokenizer::setVarIdPass2()
|
||||||
// If this is a function implementation.. add it to funclist
|
// If this is a function implementation.. add it to funclist
|
||||||
Token * start = const_cast<Token *>(isFunctionHead(tok2, "{"));
|
Token * start = const_cast<Token *>(isFunctionHead(tok2, "{"));
|
||||||
if (start) {
|
if (start) {
|
||||||
setVarIdClassFunction(classname, start, start->link(), thisClassVars, structMembers, &mVarId);
|
setVarIdClassFunction(classname, start, start->link(), thisClassVars, structMembers, mVarId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(tok2, ") %name% ("))
|
if (Token::Match(tok2, ") %name% ("))
|
||||||
|
@ -4547,7 +4550,7 @@ void Tokenizer::setVarIdPass2()
|
||||||
tok3 = tok3->linkAt(1);
|
tok3 = tok3->linkAt(1);
|
||||||
}
|
}
|
||||||
if (Token::Match(tok3, ")|} {")) {
|
if (Token::Match(tok3, ")|} {")) {
|
||||||
setVarIdClassFunction(classname, tok2, tok3->next()->link(), thisClassVars, structMembers, &mVarId);
|
setVarIdClassFunction(classname, tok2, tok3->next()->link(), thisClassVars, structMembers, mVarId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -587,20 +587,20 @@ private:
|
||||||
void unsupportedTypedef(const Token *tok) const;
|
void unsupportedTypedef(const Token *tok) const;
|
||||||
|
|
||||||
void setVarIdClassDeclaration(const Token * const startToken,
|
void setVarIdClassDeclaration(const Token * const startToken,
|
||||||
const VariableMap &variableMap,
|
VariableMap &variableMap,
|
||||||
const nonneg int scopeStartVarId,
|
const nonneg int scopeStartVarId,
|
||||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers);
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers);
|
||||||
|
|
||||||
void setVarIdStructMembers(Token **tok1,
|
void setVarIdStructMembers(Token **tok1,
|
||||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
||||||
nonneg int *varId) const;
|
nonneg int &varId) const;
|
||||||
|
|
||||||
void setVarIdClassFunction(const std::string &classname,
|
void setVarIdClassFunction(const std::string &classname,
|
||||||
Token * const startToken,
|
Token * const startToken,
|
||||||
const Token * const endToken,
|
const Token * const endToken,
|
||||||
const std::map<std::string, nonneg int> &varlist,
|
const std::map<std::string, nonneg int> &varlist,
|
||||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
||||||
nonneg int *varId_);
|
nonneg int &varId_);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output list of unknown types.
|
* Output list of unknown types.
|
||||||
|
|
|
@ -418,47 +418,47 @@ static bool isNumeric(const ValueFlow::Value& value) {
|
||||||
return value.isIntValue() || value.isFloatValue();
|
return value.isIntValue() || value.isFloatValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueFlow::combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value *result)
|
void ValueFlow::combineValueProperties(const ValueFlow::Value &value1, const ValueFlow::Value &value2, ValueFlow::Value &result)
|
||||||
{
|
{
|
||||||
if (value1.isKnown() && value2.isKnown())
|
if (value1.isKnown() && value2.isKnown())
|
||||||
result->setKnown();
|
result.setKnown();
|
||||||
else if (value1.isImpossible() || value2.isImpossible())
|
else if (value1.isImpossible() || value2.isImpossible())
|
||||||
result->setImpossible();
|
result.setImpossible();
|
||||||
else if (value1.isInconclusive() || value2.isInconclusive())
|
else if (value1.isInconclusive() || value2.isInconclusive())
|
||||||
result->setInconclusive();
|
result.setInconclusive();
|
||||||
else
|
else
|
||||||
result->setPossible();
|
result.setPossible();
|
||||||
if (value1.tokvalue)
|
if (value1.tokvalue)
|
||||||
result->tokvalue = value1.tokvalue;
|
result.tokvalue = value1.tokvalue;
|
||||||
else if (value2.tokvalue)
|
else if (value2.tokvalue)
|
||||||
result->tokvalue = value2.tokvalue;
|
result.tokvalue = value2.tokvalue;
|
||||||
if (value1.isSymbolicValue()) {
|
if (value1.isSymbolicValue()) {
|
||||||
result->valueType = value1.valueType;
|
result.valueType = value1.valueType;
|
||||||
result->tokvalue = value1.tokvalue;
|
result.tokvalue = value1.tokvalue;
|
||||||
}
|
}
|
||||||
if (value2.isSymbolicValue()) {
|
if (value2.isSymbolicValue()) {
|
||||||
result->valueType = value2.valueType;
|
result.valueType = value2.valueType;
|
||||||
result->tokvalue = value2.tokvalue;
|
result.tokvalue = value2.tokvalue;
|
||||||
}
|
}
|
||||||
if (value1.isIteratorValue())
|
if (value1.isIteratorValue())
|
||||||
result->valueType = value1.valueType;
|
result.valueType = value1.valueType;
|
||||||
if (value2.isIteratorValue())
|
if (value2.isIteratorValue())
|
||||||
result->valueType = value2.valueType;
|
result.valueType = value2.valueType;
|
||||||
result->condition = value1.condition ? value1.condition : value2.condition;
|
result.condition = value1.condition ? value1.condition : value2.condition;
|
||||||
result->varId = (value1.varId != 0) ? value1.varId : value2.varId;
|
result.varId = (value1.varId != 0) ? value1.varId : value2.varId;
|
||||||
result->varvalue = (result->varId == value1.varId) ? value1.varvalue : value2.varvalue;
|
result.varvalue = (result.varId == value1.varId) ? value1.varvalue : value2.varvalue;
|
||||||
result->errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath;
|
result.errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath;
|
||||||
result->safe = value1.safe || value2.safe;
|
result.safe = value1.safe || value2.safe;
|
||||||
if (value1.bound == ValueFlow::Value::Bound::Point || value2.bound == ValueFlow::Value::Bound::Point) {
|
if (value1.bound == ValueFlow::Value::Bound::Point || value2.bound == ValueFlow::Value::Bound::Point) {
|
||||||
if (value1.bound == ValueFlow::Value::Bound::Upper || value2.bound == ValueFlow::Value::Bound::Upper)
|
if (value1.bound == ValueFlow::Value::Bound::Upper || value2.bound == ValueFlow::Value::Bound::Upper)
|
||||||
result->bound = ValueFlow::Value::Bound::Upper;
|
result.bound = ValueFlow::Value::Bound::Upper;
|
||||||
if (value1.bound == ValueFlow::Value::Bound::Lower || value2.bound == ValueFlow::Value::Bound::Lower)
|
if (value1.bound == ValueFlow::Value::Bound::Lower || value2.bound == ValueFlow::Value::Bound::Lower)
|
||||||
result->bound = ValueFlow::Value::Bound::Lower;
|
result.bound = ValueFlow::Value::Bound::Lower;
|
||||||
}
|
}
|
||||||
if (value1.path != value2.path)
|
if (value1.path != value2.path)
|
||||||
result->path = -1;
|
result.path = -1;
|
||||||
else
|
else
|
||||||
result->path = value1.path;
|
result.path = value1.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Token *getCastTypeStartToken(const Token *parent, const Settings* settings)
|
static const Token *getCastTypeStartToken(const Token *parent, const Settings* settings)
|
||||||
|
@ -652,7 +652,7 @@ static void setTokenValue(Token* tok,
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
combineValueProperties(value1, value2, &result);
|
combineValueProperties(value1, value2, result);
|
||||||
|
|
||||||
if (Token::simpleMatch(parent, "==") && result.intvalue)
|
if (Token::simpleMatch(parent, "==") && result.intvalue)
|
||||||
continue;
|
continue;
|
||||||
|
@ -854,7 +854,7 @@ static void setTokenValue(Token* tok,
|
||||||
if (!isCompatibleValues(value1, value2))
|
if (!isCompatibleValues(value1, value2))
|
||||||
continue;
|
continue;
|
||||||
ValueFlow::Value result(0);
|
ValueFlow::Value result(0);
|
||||||
combineValueProperties(value1, value2, &result);
|
combineValueProperties(value1, value2, result);
|
||||||
if (astIsFloat(parent, false)) {
|
if (astIsFloat(parent, false)) {
|
||||||
if (!result.isIntValue() && !result.isFloatValue())
|
if (!result.isIntValue() && !result.isFloatValue())
|
||||||
continue;
|
continue;
|
||||||
|
@ -1097,7 +1097,7 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings *settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool getMinMaxValues(const ValueType* vt, const cppcheck::Platform& platform, MathLib::bigint* minValue, MathLib::bigint* maxValue);
|
static bool getMinMaxValues(const ValueType* vt, const cppcheck::Platform& platform, MathLib::bigint& minValue, MathLib::bigint& maxValue);
|
||||||
|
|
||||||
// Handle various constants..
|
// Handle various constants..
|
||||||
static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp)
|
static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp)
|
||||||
|
@ -1108,7 +1108,7 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
|
||||||
const ValueType* vt = tok->valueType();
|
const ValueType* vt = tok->valueType();
|
||||||
if (vt && vt->sign == ValueType::UNSIGNED && signedValue < 0 && ValueFlow::getSizeOf(*vt, settings) < sizeof(MathLib::bigint)) {
|
if (vt && vt->sign == ValueType::UNSIGNED && signedValue < 0 && ValueFlow::getSizeOf(*vt, settings) < sizeof(MathLib::bigint)) {
|
||||||
MathLib::bigint minValue{}, maxValue{};
|
MathLib::bigint minValue{}, maxValue{};
|
||||||
if (getMinMaxValues(tok->valueType(), *settings, &minValue, &maxValue))
|
if (getMinMaxValues(tok->valueType(), *settings, minValue, maxValue))
|
||||||
signedValue += maxValue + 1;
|
signedValue += maxValue + 1;
|
||||||
}
|
}
|
||||||
ValueFlow::Value value(signedValue);
|
ValueFlow::Value value(signedValue);
|
||||||
|
@ -2817,7 +2817,7 @@ struct ValueFlowAnalyzer : Analyzer {
|
||||||
} else {
|
} else {
|
||||||
MathLib::bigint out = 0;
|
MathLib::bigint out = 0;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
execute(tok, &pm, &out, &error, getSettings());
|
execute(tok, pm, &out, &error, getSettings());
|
||||||
if (!error)
|
if (!error)
|
||||||
result.push_back(out);
|
result.push_back(out);
|
||||||
}
|
}
|
||||||
|
@ -2844,7 +2844,7 @@ struct ValueFlowAnalyzer : Analyzer {
|
||||||
return {value->intvalue == 0};
|
return {value->intvalue == 0};
|
||||||
ProgramMemory pm = pms.get(tok, ctx, getProgramState());
|
ProgramMemory pm = pms.get(tok, ctx, getProgramState());
|
||||||
MathLib::bigint out = 0;
|
MathLib::bigint out = 0;
|
||||||
if (pm.getContainerEmptyValue(tok->exprId(), &out))
|
if (pm.getContainerEmptyValue(tok->exprId(), out))
|
||||||
return {static_cast<int>(out)};
|
return {static_cast<int>(out)};
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
|
@ -6344,9 +6344,9 @@ struct ConditionHandler {
|
||||||
ProgramMemory pm;
|
ProgramMemory pm;
|
||||||
fillFromPath(pm, initTok, path);
|
fillFromPath(pm, initTok, path);
|
||||||
fillFromPath(pm, condTok, path);
|
fillFromPath(pm, condTok, path);
|
||||||
execute(initTok, &pm, nullptr, nullptr);
|
execute(initTok, pm, nullptr, nullptr);
|
||||||
MathLib::bigint result = 1;
|
MathLib::bigint result = 1;
|
||||||
execute(condTok, &pm, &result, nullptr);
|
execute(condTok, pm, &result, nullptr);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
return;
|
return;
|
||||||
// Remove condition since for condition is not redundant
|
// Remove condition since for condition is not redundant
|
||||||
|
@ -6762,10 +6762,10 @@ static bool valueFlowForLoop2(const Token *tok,
|
||||||
ProgramMemory programMemory;
|
ProgramMemory programMemory;
|
||||||
MathLib::bigint result(0);
|
MathLib::bigint result(0);
|
||||||
bool error = false;
|
bool error = false;
|
||||||
execute(firstExpression, &programMemory, &result, &error);
|
execute(firstExpression, programMemory, &result, &error);
|
||||||
if (error)
|
if (error)
|
||||||
return false;
|
return false;
|
||||||
execute(secondExpression, &programMemory, &result, &error);
|
execute(secondExpression, programMemory, &result, &error);
|
||||||
if (result == 0) // 2nd expression is false => no looping
|
if (result == 0) // 2nd expression is false => no looping
|
||||||
return false;
|
return false;
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -6788,9 +6788,9 @@ static bool valueFlowForLoop2(const Token *tok,
|
||||||
int maxcount = 10000;
|
int maxcount = 10000;
|
||||||
while (result != 0 && !error && --maxcount > 0) {
|
while (result != 0 && !error && --maxcount > 0) {
|
||||||
endMemory = programMemory;
|
endMemory = programMemory;
|
||||||
execute(thirdExpression, &programMemory, &result, &error);
|
execute(thirdExpression, programMemory, &result, &error);
|
||||||
if (!error)
|
if (!error)
|
||||||
execute(secondExpression, &programMemory, &result, &error);
|
execute(secondExpression, programMemory, &result, &error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memory1)
|
if (memory1)
|
||||||
|
@ -6954,7 +6954,7 @@ static void valueFlowForLoop(TokenList *tokenlist, SymbolDatabase* symboldatabas
|
||||||
bool knownInitValue, partialCond;
|
bool knownInitValue, partialCond;
|
||||||
MathLib::bigint initValue, stepValue, lastValue;
|
MathLib::bigint initValue, stepValue, lastValue;
|
||||||
|
|
||||||
if (extractForLoopValues(tok, &varid, &knownInitValue, &initValue, &partialCond, &stepValue, &lastValue)) {
|
if (extractForLoopValues(tok, varid, knownInitValue, initValue, partialCond, stepValue, lastValue)) {
|
||||||
const bool executeBody = !knownInitValue || initValue <= lastValue;
|
const bool executeBody = !knownInitValue || initValue <= lastValue;
|
||||||
const Token* vartok = Token::findmatch(tok, "%varid%", bodyStart, varid);
|
const Token* vartok = Token::findmatch(tok, "%varid%", bodyStart, varid);
|
||||||
if (executeBody && vartok) {
|
if (executeBody && vartok) {
|
||||||
|
@ -7556,7 +7556,7 @@ static void valueFlowFunctionReturn(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
MathLib::bigint result = 0;
|
MathLib::bigint result = 0;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
execute(functionScope->bodyStart->next()->astOperand1(),
|
execute(functionScope->bodyStart->next()->astOperand1(),
|
||||||
&programMemory,
|
programMemory,
|
||||||
&result,
|
&result,
|
||||||
&error);
|
&error);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
@ -8631,7 +8631,7 @@ static void valueFlowDynamicBufferSize(TokenList* tokenlist, SymbolDatabase* sym
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool getMinMaxValues(const ValueType *vt, const cppcheck::Platform &platform, MathLib::bigint *minValue, MathLib::bigint *maxValue)
|
static bool getMinMaxValues(const ValueType *vt, const cppcheck::Platform &platform, MathLib::bigint &minValue, MathLib::bigint &maxValue)
|
||||||
{
|
{
|
||||||
if (!vt || !vt->isIntegral() || vt->pointer)
|
if (!vt || !vt->isIntegral() || vt->pointer)
|
||||||
return false;
|
return false;
|
||||||
|
@ -8661,23 +8661,23 @@ static bool getMinMaxValues(const ValueType *vt, const cppcheck::Platform &platf
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bits == 1) {
|
if (bits == 1) {
|
||||||
*minValue = 0;
|
minValue = 0;
|
||||||
*maxValue = 1;
|
maxValue = 1;
|
||||||
} else if (bits < 62) {
|
} else if (bits < 62) {
|
||||||
if (vt->sign == ValueType::Sign::UNSIGNED) {
|
if (vt->sign == ValueType::Sign::UNSIGNED) {
|
||||||
*minValue = 0;
|
minValue = 0;
|
||||||
*maxValue = (1LL << bits) - 1;
|
maxValue = (1LL << bits) - 1;
|
||||||
} else {
|
} else {
|
||||||
*minValue = -(1LL << (bits - 1));
|
minValue = -(1LL << (bits - 1));
|
||||||
*maxValue = (1LL << (bits - 1)) - 1;
|
maxValue = (1LL << (bits - 1)) - 1;
|
||||||
}
|
}
|
||||||
} else if (bits == 64) {
|
} else if (bits == 64) {
|
||||||
if (vt->sign == ValueType::Sign::UNSIGNED) {
|
if (vt->sign == ValueType::Sign::UNSIGNED) {
|
||||||
*minValue = 0;
|
minValue = 0;
|
||||||
*maxValue = LLONG_MAX; // todo max unsigned value
|
maxValue = LLONG_MAX; // todo max unsigned value
|
||||||
} else {
|
} else {
|
||||||
*minValue = LLONG_MIN;
|
minValue = LLONG_MIN;
|
||||||
*maxValue = LLONG_MAX;
|
maxValue = LLONG_MAX;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -8686,7 +8686,7 @@ static bool getMinMaxValues(const ValueType *vt, const cppcheck::Platform &platf
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool getMinMaxValues(const std::string &typestr, const Settings *settings, MathLib::bigint *minvalue, MathLib::bigint *maxvalue)
|
static bool getMinMaxValues(const std::string &typestr, const Settings *settings, MathLib::bigint &minvalue, MathLib::bigint &maxvalue)
|
||||||
{
|
{
|
||||||
TokenList typeTokens(settings);
|
TokenList typeTokens(settings);
|
||||||
std::istringstream istr(typestr+";");
|
std::istringstream istr(typestr+";");
|
||||||
|
@ -8732,8 +8732,8 @@ static void valueFlowSafeFunctions(TokenList* tokenlist, SymbolDatabase* symbold
|
||||||
}
|
}
|
||||||
|
|
||||||
MathLib::bigint low, high;
|
MathLib::bigint low, high;
|
||||||
bool isLow = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, &low);
|
bool isLow = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, low);
|
||||||
bool isHigh = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, &high);
|
bool isHigh = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, high);
|
||||||
|
|
||||||
if (!isLow && !isHigh && !all)
|
if (!isLow && !isHigh && !all)
|
||||||
continue;
|
continue;
|
||||||
|
@ -8743,7 +8743,7 @@ static void valueFlowSafeFunctions(TokenList* tokenlist, SymbolDatabase* symbold
|
||||||
|
|
||||||
if ((!isLow || !isHigh) && all) {
|
if ((!isLow || !isHigh) && all) {
|
||||||
MathLib::bigint minValue, maxValue;
|
MathLib::bigint minValue, maxValue;
|
||||||
if (getMinMaxValues(arg.valueType(), *settings, &minValue, &maxValue)) {
|
if (getMinMaxValues(arg.valueType(), *settings, minValue, maxValue)) {
|
||||||
if (!isLow)
|
if (!isLow)
|
||||||
low = minValue;
|
low = minValue;
|
||||||
if (!isHigh)
|
if (!isHigh)
|
||||||
|
@ -8808,7 +8808,7 @@ static void valueFlowUnknownFunctionReturn(TokenList *tokenlist, const Settings
|
||||||
// Get min/max values for return type
|
// Get min/max values for return type
|
||||||
const std::string &typestr = settings->library.returnValueType(tok->previous());
|
const std::string &typestr = settings->library.returnValueType(tok->previous());
|
||||||
MathLib::bigint minvalue, maxvalue;
|
MathLib::bigint minvalue, maxvalue;
|
||||||
if (!getMinMaxValues(typestr, settings, &minvalue, &maxvalue))
|
if (!getMinMaxValues(typestr, settings, minvalue, maxvalue))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (MathLib::bigint value : unknownValues) {
|
for (MathLib::bigint value : unknownValues) {
|
||||||
|
|
|
@ -126,7 +126,7 @@ namespace ValueFlow {
|
||||||
|
|
||||||
const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope = nullptr, bool smallest = true);
|
const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope = nullptr, bool smallest = true);
|
||||||
|
|
||||||
void combineValueProperties(const Value& value1, const Value& value2, Value* result);
|
void combineValueProperties(const Value& value1, const Value& value2, Value& result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // valueflowH
|
#endif // valueflowH
|
||||||
|
|
|
@ -662,10 +662,10 @@ private:
|
||||||
ASSERT(library.loadxmldata(xmldata, sizeof(xmldata)));
|
ASSERT(library.loadxmldata(xmldata, sizeof(xmldata)));
|
||||||
ASSERT(library.functions.empty());
|
ASSERT(library.functions.empty());
|
||||||
|
|
||||||
ASSERT(Library::ismemory(library.getAllocFuncInfo("CreateX")));
|
|
||||||
ASSERT_EQUALS(library.allocId("CreateX"), library.deallocId("DeleteX"));
|
|
||||||
const Library::AllocFunc* af = library.getAllocFuncInfo("CreateX");
|
const Library::AllocFunc* af = library.getAllocFuncInfo("CreateX");
|
||||||
ASSERT(af && af->arg == -1);
|
ASSERT(af && af->arg == -1);
|
||||||
|
ASSERT(Library::ismemory(af));
|
||||||
|
ASSERT_EQUALS(library.allocId("CreateX"), library.deallocId("DeleteX"));
|
||||||
const Library::AllocFunc* df = library.getDeallocFuncInfo("DeleteX");
|
const Library::AllocFunc* df = library.getDeallocFuncInfo("DeleteX");
|
||||||
ASSERT(df && df->arg == 1);
|
ASSERT(df && df->arg == 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue