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
/// @{
/**
* @brief Interface class that cppcheck uses to communicate with the checks.
* All checking classes must inherit from this class
@ -158,19 +157,27 @@ protected:
reportError(errmsg);
}
std::list<const Token *> getErrorPath(const Token *errtok, const ValueFlow::Value *value) const {
std::list<const Token*> errorPath;
void reportError(const ErrorPath &errorPath, Severity::SeverityType severity, const char id[], const std::string &msg, const CWE &cwe, bool inconclusive) {
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) {
errorPath.push_back(errtok);
errorPath.push_back(ErrorPathItem(errtok,""));
} else if (_settings->verbose) {
errorPath = value->callstack;
errorPath.push_back(errtok);
errorPath = value->errorPath;
errorPath.push_back(ErrorPathItem(errtok,""));
} else {
if (value->condition)
errorPath.push_back(value->condition);
errorPath.push_back(ErrorPathItem(value->condition, "condition '" + value->condition->expressionString() + "'"));
//else if (!value->isKnown() || value->defaultArg)
// errorPath = value->callstack;
errorPath.push_back(errtok);
errorPath.push_back(ErrorPathItem(errtok,""));
}
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)
{
const std::list<const Token *> errorPath = getErrorPath(tok, &index);
const ErrorPath errorPath = getErrorPath(tok, &index);
std::ostringstream errmsg;
if (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))
return;
const std::list<const Token*> errorPath = getErrorPath(tok,value);
const ErrorPath errorPath = getErrorPath(tok,value);
if (value->condition) {
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;
}
const std::list<const Token *> errorPath = getErrorPath(tok, value);
const ErrorPath errorPath = getErrorPath(tok, value);
std::ostringstream errmsg;
if (value->condition)

View File

@ -111,6 +111,25 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack
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)
: _id(errmsg->Attribute("id")),
_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);
for (const tinyxml2::XMLElement *e = errmsg->FirstChildElement(); e; e = e->NextSiblingElement()) {
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
{
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
* should implement.
@ -190,6 +194,7 @@ public:
}
FileLocation(const Token* tok, const TokenList* list);
FileLocation(const Token* tok, const std::string &info, const TokenList* tokenList);
/**
* Return the filename.
@ -214,12 +219,14 @@ public:
private:
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, 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, 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();
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.varId = (value1->varId != 0U) ? value1->varId : value2->varId;
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)
result.valueKind = value1->valueKind;
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();
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();
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)
it->callstack.push_back(argtok);
it->errorPath.push_back(ErrorPathItem(argtok, "function call argument"));
// passed values are not "known"..
for (std::list<ValueFlow::Value>::iterator it = argvalues.begin(); it != argvalues.end(); ++it) {

View File

@ -34,9 +34,12 @@ class Settings;
namespace ValueFlow {
class CPPCHECKLIB Value {
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) {}
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 {
@ -105,10 +108,10 @@ namespace ValueFlow {
/** For calculated values - variable value that calculated value depends on */
long long varvalue;
/** Condition that this value depends on (TODO: replace with a 'callstack') */
/** Condition that this value depends on */
const Token *condition;
std::list<const Token *> callstack;
ErrorPath errorPath;
/** For calculated values - varId that calculated value depends on */
unsigned int varId;