ErrorLogger: Added ErrorPath where each item has token and info
This commit is contained in:
parent
e65d6d3c67
commit
c617851567
23
lib/check.h
23
lib/check.h
|
@ -45,7 +45,6 @@ namespace tinyxml2 {
|
||||||
/// @addtogroup Core
|
/// @addtogroup Core
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Interface class that cppcheck uses to communicate with the checks.
|
* @brief Interface class that cppcheck uses to communicate with the checks.
|
||||||
* All checking classes must inherit from this class
|
* All checking classes must inherit from this class
|
||||||
|
@ -158,19 +157,27 @@ protected:
|
||||||
reportError(errmsg);
|
reportError(errmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<const Token *> getErrorPath(const Token *errtok, const ValueFlow::Value *value) const {
|
void reportError(const ErrorPath &errorPath, Severity::SeverityType severity, const char id[], const std::string &msg, const CWE &cwe, bool inconclusive) {
|
||||||
std::list<const Token*> errorPath;
|
const ErrorLogger::ErrorMessage errmsg(errorPath, _tokenizer ? &_tokenizer->list : nullptr, severity, id, msg, cwe, inconclusive);
|
||||||
|
if (_errorLogger)
|
||||||
|
_errorLogger->reportErr(errmsg);
|
||||||
|
else
|
||||||
|
reportError(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorPath getErrorPath(const Token *errtok, const ValueFlow::Value *value) const {
|
||||||
|
ErrorPath errorPath;
|
||||||
if (!value) {
|
if (!value) {
|
||||||
errorPath.push_back(errtok);
|
errorPath.push_back(ErrorPathItem(errtok,""));
|
||||||
} else if (_settings->verbose) {
|
} else if (_settings->verbose) {
|
||||||
errorPath = value->callstack;
|
errorPath = value->errorPath;
|
||||||
errorPath.push_back(errtok);
|
errorPath.push_back(ErrorPathItem(errtok,""));
|
||||||
} else {
|
} else {
|
||||||
if (value->condition)
|
if (value->condition)
|
||||||
errorPath.push_back(value->condition);
|
errorPath.push_back(ErrorPathItem(value->condition, "condition '" + value->condition->expressionString() + "'"));
|
||||||
//else if (!value->isKnown() || value->defaultArg)
|
//else if (!value->isKnown() || value->defaultArg)
|
||||||
// errorPath = value->callstack;
|
// errorPath = value->callstack;
|
||||||
errorPath.push_back(errtok);
|
errorPath.push_back(ErrorPathItem(errtok,""));
|
||||||
}
|
}
|
||||||
return errorPath;
|
return errorPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1780,7 +1780,7 @@ void CheckBufferOverrun::negativeIndexError(const Token *tok, MathLib::bigint in
|
||||||
|
|
||||||
void CheckBufferOverrun::negativeIndexError(const Token *tok, const ValueFlow::Value &index)
|
void CheckBufferOverrun::negativeIndexError(const Token *tok, const ValueFlow::Value &index)
|
||||||
{
|
{
|
||||||
const std::list<const Token *> errorPath = getErrorPath(tok, &index);
|
const ErrorPath errorPath = getErrorPath(tok, &index);
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
if (index.condition)
|
if (index.condition)
|
||||||
errmsg << ValueFlow::eitherTheConditionIsRedundant(index.condition)
|
errmsg << ValueFlow::eitherTheConditionIsRedundant(index.condition)
|
||||||
|
|
|
@ -473,7 +473,7 @@ void CheckNullPointer::nullPointerError(const Token *tok, const std::string &var
|
||||||
if (!_settings->isEnabled(value, inconclusive))
|
if (!_settings->isEnabled(value, inconclusive))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::list<const Token*> errorPath = getErrorPath(tok,value);
|
const ErrorPath errorPath = getErrorPath(tok,value);
|
||||||
|
|
||||||
if (value->condition) {
|
if (value->condition) {
|
||||||
reportError(errorPath, Severity::warning, "nullPointerRedundantCheck", errmsgcond, CWE476, inconclusive || value->inconclusive);
|
reportError(errorPath, Severity::warning, "nullPointerRedundantCheck", errmsgcond, CWE476, inconclusive || value->inconclusive);
|
||||||
|
|
|
@ -1656,7 +1656,7 @@ void CheckOther::zerodivError(const Token *tok, const ValueFlow::Value *value)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::list<const Token *> errorPath = getErrorPath(tok, value);
|
const ErrorPath errorPath = getErrorPath(tok, value);
|
||||||
|
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
if (value->condition)
|
if (value->condition)
|
||||||
|
|
|
@ -111,6 +111,25 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack
|
||||||
setmsg(msg);
|
setmsg(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorLogger::ErrorMessage::ErrorMessage(const ErrorPath &errorPath, const TokenList *tokenList, Severity::SeverityType severity, const char id[], const std::string &msg, const CWE &cwe, bool inconclusive)
|
||||||
|
: _id(id), _severity(severity), _cwe(cwe.id), _inconclusive(inconclusive)
|
||||||
|
{
|
||||||
|
// Format callstack
|
||||||
|
for (ErrorPath::const_iterator it = errorPath.begin(); it != errorPath.end(); ++it) {
|
||||||
|
const Token *tok = it->first;
|
||||||
|
const std::string &info = it->second;
|
||||||
|
|
||||||
|
// --errorlist can provide null values here
|
||||||
|
if (tok)
|
||||||
|
_callStack.push_back(ErrorLogger::ErrorMessage::FileLocation(tok, info, tokenList));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenList && !tokenList->getFiles().empty())
|
||||||
|
file0 = tokenList->getFiles()[0];
|
||||||
|
|
||||||
|
setmsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
ErrorLogger::ErrorMessage::ErrorMessage(const tinyxml2::XMLElement * const errmsg)
|
ErrorLogger::ErrorMessage::ErrorMessage(const tinyxml2::XMLElement * const errmsg)
|
||||||
: _id(errmsg->Attribute("id")),
|
: _id(errmsg->Attribute("id")),
|
||||||
_severity(Severity::fromString(errmsg->Attribute("severity"))),
|
_severity(Severity::fromString(errmsg->Attribute("severity"))),
|
||||||
|
@ -125,7 +144,10 @@ ErrorLogger::ErrorMessage::ErrorMessage(const tinyxml2::XMLElement * const errms
|
||||||
_inconclusive = attr && (std::strcmp(attr, "true") == 0);
|
_inconclusive = attr && (std::strcmp(attr, "true") == 0);
|
||||||
for (const tinyxml2::XMLElement *e = errmsg->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
for (const tinyxml2::XMLElement *e = errmsg->FirstChildElement(); e; e = e->NextSiblingElement()) {
|
||||||
if (std::strcmp(e->Name(),"location")==0) {
|
if (std::strcmp(e->Name(),"location")==0) {
|
||||||
_callStack.push_back(ErrorLogger::ErrorMessage::FileLocation(e->Attribute("file"), std::atoi(e->Attribute("line"))));
|
const char *strfile = e->Attribute("file");
|
||||||
|
const char *strinfo = e->Attribute("info");
|
||||||
|
const char *strline = e->Attribute("line");
|
||||||
|
_callStack.push_back(ErrorLogger::ErrorMessage::FileLocation(strfile, strinfo ? strinfo : "", std::atoi(strline)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,6 +475,11 @@ ErrorLogger::ErrorMessage::FileLocation::FileLocation(const Token* tok, const To
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorLogger::ErrorMessage::FileLocation::FileLocation(const Token* tok, const std::string &info, const TokenList* list)
|
||||||
|
: line(tok->linenr()), fileNumber(tok->fileIndex()), _file(list->file(tok)), _info(info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::string ErrorLogger::ErrorMessage::FileLocation::getfile(bool convert) const
|
std::string ErrorLogger::ErrorMessage::FileLocation::getfile(bool convert) const
|
||||||
{
|
{
|
||||||
if (convert)
|
if (convert)
|
||||||
|
|
|
@ -160,6 +160,10 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::pair<const Token *, std::string> ErrorPathItem;
|
||||||
|
typedef std::list<ErrorPathItem> ErrorPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is an interface, which the class responsible of error logging
|
* @brief This is an interface, which the class responsible of error logging
|
||||||
* should implement.
|
* should implement.
|
||||||
|
@ -190,6 +194,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
FileLocation(const Token* tok, const TokenList* list);
|
FileLocation(const Token* tok, const TokenList* list);
|
||||||
|
FileLocation(const Token* tok, const std::string &info, const TokenList* tokenList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the filename.
|
* Return the filename.
|
||||||
|
@ -214,12 +219,14 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _file;
|
std::string _file;
|
||||||
|
std::string _info;
|
||||||
};
|
};
|
||||||
|
|
||||||
ErrorMessage(const std::list<FileLocation> &callStack, const std::string& file1, Severity::SeverityType severity, const std::string &msg, const std::string &id, bool inconclusive);
|
ErrorMessage(const std::list<FileLocation> &callStack, const std::string& file1, Severity::SeverityType severity, const std::string &msg, const std::string &id, bool inconclusive);
|
||||||
ErrorMessage(const std::list<FileLocation> &callStack, const std::string& file1, Severity::SeverityType severity, const std::string &msg, const std::string &id, const CWE &cwe, bool inconclusive);
|
ErrorMessage(const std::list<FileLocation> &callStack, const std::string& file1, Severity::SeverityType severity, const std::string &msg, const std::string &id, const CWE &cwe, bool inconclusive);
|
||||||
ErrorMessage(const std::list<const Token*>& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive);
|
ErrorMessage(const std::list<const Token*>& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive);
|
||||||
ErrorMessage(const std::list<const Token*>& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, const CWE &cwe, bool inconclusive);
|
ErrorMessage(const std::list<const Token*>& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, const CWE &cwe, bool inconclusive);
|
||||||
|
ErrorMessage(const ErrorPath &errorPath, const TokenList *tokenList, Severity::SeverityType severity, const char id[], const std::string &msg, const CWE &cwe, bool inconclusive);
|
||||||
ErrorMessage();
|
ErrorMessage();
|
||||||
explicit ErrorMessage(const tinyxml2::XMLElement * const errmsg);
|
explicit ErrorMessage(const tinyxml2::XMLElement * const errmsg);
|
||||||
|
|
||||||
|
|
|
@ -365,7 +365,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
|
||||||
result.inconclusive = value1->inconclusive | value2->inconclusive;
|
result.inconclusive = value1->inconclusive | value2->inconclusive;
|
||||||
result.varId = (value1->varId != 0U) ? value1->varId : value2->varId;
|
result.varId = (value1->varId != 0U) ? 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.callstack = (value1->callstack.empty() ? value2 : value1)->callstack;
|
result.errorPath = (value1->errorPath.empty() ? value2 : value1)->errorPath;
|
||||||
if (value1->valueKind == value2->valueKind)
|
if (value1->valueKind == value2->valueKind)
|
||||||
result.valueKind = value1->valueKind;
|
result.valueKind = value1->valueKind;
|
||||||
const float floatValue1 = value1->isIntValue() ? value1->intvalue : value1->floatValue;
|
const float floatValue1 = value1->isIntValue() ? value1->intvalue : value1->floatValue;
|
||||||
|
@ -1972,7 +1972,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
|
||||||
|
|
||||||
std::list<ValueFlow::Value> values = tok->astOperand2()->values();
|
std::list<ValueFlow::Value> values = tok->astOperand2()->values();
|
||||||
for (std::list<ValueFlow::Value>::iterator it = values.begin(); it != values.end(); ++it)
|
for (std::list<ValueFlow::Value>::iterator it = values.begin(); it != values.end(); ++it)
|
||||||
it->callstack.push_back(tok->astOperand2());
|
it->errorPath.push_back(ErrorPathItem(tok->astOperand2(),"assignment"));
|
||||||
const bool constValue = tok->astOperand2()->isNumber();
|
const bool constValue = tok->astOperand2()->isNumber();
|
||||||
|
|
||||||
if (tokenlist->isCPP() && Token::Match(var->typeStartToken(), "bool|_Bool")) {
|
if (tokenlist->isCPP() && Token::Match(var->typeStartToken(), "bool|_Bool")) {
|
||||||
|
@ -2771,9 +2771,9 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// callstack..
|
// Error path..
|
||||||
for (std::list<ValueFlow::Value>::iterator it = argvalues.begin(); it != argvalues.end(); ++it)
|
for (std::list<ValueFlow::Value>::iterator it = argvalues.begin(); it != argvalues.end(); ++it)
|
||||||
it->callstack.push_back(argtok);
|
it->errorPath.push_back(ErrorPathItem(argtok, "function call argument"));
|
||||||
|
|
||||||
// passed values are not "known"..
|
// passed values are not "known"..
|
||||||
for (std::list<ValueFlow::Value>::iterator it = argvalues.begin(); it != argvalues.end(); ++it) {
|
for (std::list<ValueFlow::Value>::iterator it = argvalues.begin(); it != argvalues.end(); ++it) {
|
||||||
|
|
|
@ -34,9 +34,12 @@ class Settings;
|
||||||
namespace ValueFlow {
|
namespace ValueFlow {
|
||||||
class CPPCHECKLIB Value {
|
class CPPCHECKLIB Value {
|
||||||
public:
|
public:
|
||||||
|
typedef std::pair<const Token *, std::string> ErrorPathItem;
|
||||||
|
typedef std::list<ErrorPathItem> ErrorPath;
|
||||||
|
|
||||||
explicit Value(long long val = 0) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
|
explicit Value(long long val = 0) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
|
||||||
Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {
|
Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {
|
||||||
callstack.push_back(c);
|
errorPath.push_back(ErrorPathItem(c, "condition"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Value &rhs) const {
|
bool operator==(const Value &rhs) const {
|
||||||
|
@ -105,10 +108,10 @@ namespace ValueFlow {
|
||||||
/** For calculated values - variable value that calculated value depends on */
|
/** For calculated values - variable value that calculated value depends on */
|
||||||
long long varvalue;
|
long long varvalue;
|
||||||
|
|
||||||
/** Condition that this value depends on (TODO: replace with a 'callstack') */
|
/** Condition that this value depends on */
|
||||||
const Token *condition;
|
const Token *condition;
|
||||||
|
|
||||||
std::list<const Token *> callstack;
|
ErrorPath errorPath;
|
||||||
|
|
||||||
/** For calculated values - varId that calculated value depends on */
|
/** For calculated values - varId that calculated value depends on */
|
||||||
unsigned int varId;
|
unsigned int varId;
|
||||||
|
|
Loading…
Reference in New Issue