avoid some unchecked pointer dereferences (#4811)

This commit is contained in:
Oliver Stöneberg 2023-03-02 22:05:41 +01:00 committed by GitHub
parent 215124461e
commit b70e1d5461
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 292 additions and 290 deletions

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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);

View File

@ -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));

View File

@ -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;

View File

@ -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);

View File

@ -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;
} }

View File

@ -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);

View File

@ -183,37 +183,36 @@ static int getMinFormatStringOutputLength(const std::vector<const Token*> &param
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
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;
} }

View File

@ -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 &not1, 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, &not_, &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, &not1, &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, &not2, &op2, &value2, &expr2, &inconclusive)); parseable &= (parseComparison(comp2, not2, op2, value2, expr2, inconclusive));
if (inconclusive && !printInconclusive) if (inconclusive && !printInconclusive)
continue; continue;

View File

@ -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)))

View File

@ -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);

View File

@ -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

View File

@ -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))

View File

@ -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:

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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);
} }
} }
} }

View File

@ -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;
} }

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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++) {

View File

@ -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_,

View File

@ -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;
} }

View File

@ -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 {

View File

@ -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);
} }
} }
} }

View File

@ -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.

View File

@ -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) {

View File

@ -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

View File

@ -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);
} }