ErrorLogger: Added ErrorPath where each item has token and info

This commit is contained in:
Daniel Marjamäki 2017-05-16 22:38:13 +02:00
parent e65d6d3c67
commit c617851567
8 changed files with 63 additions and 19 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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