ExprEngine: Print some 'debug' output
This commit is contained in:
parent
bf55e835aa
commit
5f0f8afc27
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "exprengine.h"
|
#include "exprengine.h"
|
||||||
|
#include "astutils.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "symboldatabase.h"
|
#include "symboldatabase.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
|
@ -51,29 +52,71 @@ std::string ExprEngine::str(int128_t value)
|
||||||
static ExprEngine::ValuePtr getValueRangeFromValueType(const std::string &name, const ValueType *vt, const cppcheck::Platform &platform);
|
static ExprEngine::ValuePtr getValueRangeFromValueType(const std::string &name, const ValueType *vt, const cppcheck::Platform &platform);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
class TrackExecution {
|
||||||
|
public:
|
||||||
|
TrackExecution() : dataIndex(0) {}
|
||||||
|
std::map<const Token *, std::vector<std::string>> map;
|
||||||
|
int getNewDataIndex() {
|
||||||
|
return dataIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void newValue(const Token *tok, ExprEngine::ValuePtr value) {
|
||||||
|
if (!tok)
|
||||||
|
return;
|
||||||
|
if (!value)
|
||||||
|
map[tok].push_back(tok->expressionString() + "=TODO_NO_VALUE");
|
||||||
|
/*
|
||||||
|
else if (value->name[0] == '$')
|
||||||
|
map[tok].push_back(tok->expressionString() + "=(" + value->name + "," + value->getRange() + ")");
|
||||||
|
else
|
||||||
|
map[tok].push_back(tok->expressionString() + "=" + value->name);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void state(const Token *tok, const std::string &s) {
|
||||||
|
map[tok].push_back(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print() {
|
||||||
|
std::set<std::pair<int,int>> locations;
|
||||||
|
for (auto it : map) {
|
||||||
|
locations.emplace(it.first->linenr(), it.first->column());
|
||||||
|
}
|
||||||
|
for (const std::pair<int,int> &loc : locations) {
|
||||||
|
int lineNumber = loc.first;
|
||||||
|
int column = loc.second;
|
||||||
|
for (auto &it : map) {
|
||||||
|
const Token *tok = it.first;
|
||||||
|
if (lineNumber != tok->linenr())
|
||||||
|
continue;
|
||||||
|
const std::vector<std::string> &dumps = it.second;
|
||||||
|
for (const std::string &dump : dumps)
|
||||||
|
std::cout << lineNumber << ":" << column << ": " << dump << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
int dataIndex;
|
||||||
|
};
|
||||||
|
|
||||||
class Data {
|
class Data {
|
||||||
public:
|
public:
|
||||||
Data(int *symbolValueIndex, const Tokenizer *tokenizer, const Settings *settings, const std::vector<ExprEngine::Callback> &callbacks)
|
Data(int *symbolValueIndex, const Tokenizer *tokenizer, const Settings *settings, const std::vector<ExprEngine::Callback> &callbacks, TrackExecution *trackExecution)
|
||||||
: symbolValueIndex(symbolValueIndex)
|
: symbolValueIndex(symbolValueIndex)
|
||||||
, tokenizer(tokenizer)
|
, tokenizer(tokenizer)
|
||||||
, settings(settings)
|
, settings(settings)
|
||||||
, callbacks(callbacks) {}
|
, callbacks(callbacks)
|
||||||
|
, mTrackExecution(trackExecution)
|
||||||
|
, dataIndex(trackExecution->getNewDataIndex()) {}
|
||||||
typedef std::map<nonneg int, std::shared_ptr<ExprEngine::Value>> Memory;
|
typedef std::map<nonneg int, std::shared_ptr<ExprEngine::Value>> Memory;
|
||||||
Memory memory;
|
Memory memory;
|
||||||
int *symbolValueIndex;
|
int * const symbolValueIndex;
|
||||||
const Tokenizer *tokenizer;
|
const Tokenizer * const tokenizer;
|
||||||
const Settings *settings;
|
const Settings * const settings;
|
||||||
const std::vector<ExprEngine::Callback> &callbacks;
|
const std::vector<ExprEngine::Callback> &callbacks;
|
||||||
|
|
||||||
void printMemory() const {
|
|
||||||
const SymbolDatabase *symbolDatabase = tokenizer->getSymbolDatabase();
|
|
||||||
for (Memory::const_iterator mem = memory.cbegin(); mem != memory.cend(); ++mem) {
|
|
||||||
std::cout << symbolDatabase->getVariableFromVarId(mem->first)->name() << " name:" << mem->second->name << " range:" << mem->second->getRange() << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Data getData(const Token *cond, bool trueData) {
|
Data getData(const Token *cond, bool trueData) {
|
||||||
Data ret(symbolValueIndex, tokenizer, settings, callbacks);
|
Data ret(symbolValueIndex, tokenizer, settings, callbacks, mTrackExecution);
|
||||||
for (Memory::const_iterator mem = memory.cbegin(); mem != memory.cend(); ++mem) {
|
for (Memory::const_iterator mem = memory.cbegin(); mem != memory.cend(); ++mem) {
|
||||||
ret.memory[mem->first] = mem->second;
|
ret.memory[mem->first] = mem->second;
|
||||||
|
|
||||||
|
@ -81,10 +124,15 @@ namespace {
|
||||||
const int128_t rhsValue = MathLib::toLongNumber(cond->astOperand2()->str());
|
const int128_t rhsValue = MathLib::toLongNumber(cond->astOperand2()->str());
|
||||||
if (auto intRange = std::dynamic_pointer_cast<ExprEngine::IntRange>(mem->second)) {
|
if (auto intRange = std::dynamic_pointer_cast<ExprEngine::IntRange>(mem->second)) {
|
||||||
if (cond->str() == ">") {
|
if (cond->str() == ">") {
|
||||||
if (trueData && intRange->minValue <= rhsValue)
|
if (trueData && intRange->minValue <= rhsValue) {
|
||||||
ret.memory[mem->first] = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), rhsValue + 1, intRange->maxValue);
|
auto val = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), rhsValue + 1, intRange->maxValue);
|
||||||
else if (!trueData && intRange->maxValue > rhsValue)
|
ret.trackAssignment(cond, val);
|
||||||
ret.memory[mem->first] = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), intRange->minValue, rhsValue);
|
ret.memory[mem->first] = val;
|
||||||
|
} else if (!trueData && intRange->maxValue > rhsValue) {
|
||||||
|
auto val = std::make_shared<ExprEngine::IntRange>(getNewSymbolName(), intRange->minValue, rhsValue);
|
||||||
|
ret.trackAssignment(cond, val);
|
||||||
|
ret.memory[mem->first] = val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,17 +151,45 @@ namespace {
|
||||||
return std::shared_ptr<ExprEngine::ArrayValue>();
|
return std::shared_ptr<ExprEngine::ArrayValue>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprEngine::ValuePtr getValue(unsigned int varId, const ValueType *valueType) {
|
ExprEngine::ValuePtr getValue(unsigned int varId, const ValueType *valueType, const Token *tok) {
|
||||||
const Memory::const_iterator it = memory.find(varId);
|
const Memory::const_iterator it = memory.find(varId);
|
||||||
if (it != memory.end())
|
if (it != memory.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
if (!valueType)
|
if (!valueType)
|
||||||
return ExprEngine::ValuePtr();
|
return ExprEngine::ValuePtr();
|
||||||
ExprEngine::ValuePtr value = getValueRangeFromValueType(getNewSymbolName(), valueType, *settings);
|
ExprEngine::ValuePtr value = getValueRangeFromValueType(getNewSymbolName(), valueType, *settings);
|
||||||
if (value)
|
if (value) {
|
||||||
|
if (tok)
|
||||||
|
trackAssignment(tok, value);
|
||||||
memory[varId] = value;
|
memory[varId] = value;
|
||||||
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void trackAssignment(const Token *tok, ExprEngine::ValuePtr value) {
|
||||||
|
return mTrackExecution->newValue(tok, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void trackProgramState(const Token *tok) {
|
||||||
|
if (memory.empty())
|
||||||
|
return;
|
||||||
|
const SymbolDatabase * const symbolDatabase = tokenizer->getSymbolDatabase();
|
||||||
|
std::ostringstream s;
|
||||||
|
s << "{"; // << dataIndex << ":";
|
||||||
|
for (auto mem : memory) {
|
||||||
|
ExprEngine::ValuePtr value = mem.second;
|
||||||
|
s << " " << symbolDatabase->getVariableFromVarId(mem.first)->name() << "=";
|
||||||
|
if (value->name[0] == '$')
|
||||||
|
s << "(" << value->name << "," << value->getRange() << ")";
|
||||||
|
else
|
||||||
|
s << value->name;
|
||||||
|
}
|
||||||
|
s << "}";
|
||||||
|
mTrackExecution->state(tok, s.str());
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
TrackExecution * const mTrackExecution;
|
||||||
|
const int dataIndex;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +366,7 @@ static ExprEngine::ValuePtr executeAssign(const Token *tok, Data &data)
|
||||||
call(data.callbacks, tok, rhsValue);
|
call(data.callbacks, tok, rhsValue);
|
||||||
|
|
||||||
const Token *lhsToken = tok->astOperand1();
|
const Token *lhsToken = tok->astOperand1();
|
||||||
|
data.trackAssignment(lhsToken, rhsValue);
|
||||||
if (lhsToken->varId() > 0) {
|
if (lhsToken->varId() > 0) {
|
||||||
data.memory[lhsToken->varId()] = rhsValue;
|
data.memory[lhsToken->varId()] = rhsValue;
|
||||||
} else if (lhsToken->str() == "[") {
|
} else if (lhsToken->str() == "[") {
|
||||||
|
@ -311,7 +388,8 @@ static ExprEngine::ValuePtr executeAssign(const Token *tok, Data &data)
|
||||||
|
|
||||||
static ExprEngine::ValuePtr executeFunctionCall(const Token *tok, Data &data)
|
static ExprEngine::ValuePtr executeFunctionCall(const Token *tok, Data &data)
|
||||||
{
|
{
|
||||||
(void)executeExpression(tok->astOperand2(), data);
|
for (const Token *argtok : getArguments(tok))
|
||||||
|
(void)executeExpression(argtok, data);
|
||||||
auto val = getValueRangeFromValueType(data.getNewSymbolName(), tok->valueType(), *data.settings);
|
auto val = getValueRangeFromValueType(data.getNewSymbolName(), tok->valueType(), *data.settings);
|
||||||
call(data.callbacks, tok, val);
|
call(data.callbacks, tok, val);
|
||||||
return val;
|
return val;
|
||||||
|
@ -333,7 +411,7 @@ static ExprEngine::ValuePtr executeDot(const Token *tok, Data &data)
|
||||||
{
|
{
|
||||||
if (!tok->astOperand1() || !tok->astOperand1()->varId())
|
if (!tok->astOperand1() || !tok->astOperand1()->varId())
|
||||||
return ExprEngine::ValuePtr();
|
return ExprEngine::ValuePtr();
|
||||||
std::shared_ptr<ExprEngine::StructValue> structValue = std::dynamic_pointer_cast<ExprEngine::StructValue>(data.getValue(tok->astOperand1()->varId(), nullptr));
|
std::shared_ptr<ExprEngine::StructValue> structValue = std::dynamic_pointer_cast<ExprEngine::StructValue>(data.getValue(tok->astOperand1()->varId(), nullptr, nullptr));
|
||||||
if (!structValue)
|
if (!structValue)
|
||||||
return ExprEngine::ValuePtr();
|
return ExprEngine::ValuePtr();
|
||||||
return structValue->getValueOfMember(tok->astOperand2()->str());
|
return structValue->getValueOfMember(tok->astOperand2()->str());
|
||||||
|
@ -364,7 +442,7 @@ static ExprEngine::ValuePtr executeDeref(const Token *tok, Data &data)
|
||||||
if (pval) {
|
if (pval) {
|
||||||
auto addressOf = std::dynamic_pointer_cast<ExprEngine::AddressOfValue>(pval);
|
auto addressOf = std::dynamic_pointer_cast<ExprEngine::AddressOfValue>(pval);
|
||||||
if (addressOf) {
|
if (addressOf) {
|
||||||
auto val = data.getValue(addressOf->varId, tok->valueType());
|
auto val = data.getValue(addressOf->varId, tok->valueType(), tok);
|
||||||
call(data.callbacks, tok, val);
|
call(data.callbacks, tok, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -380,7 +458,7 @@ static ExprEngine::ValuePtr executeDeref(const Token *tok, Data &data)
|
||||||
|
|
||||||
static ExprEngine::ValuePtr executeVariable(const Token *tok, Data &data)
|
static ExprEngine::ValuePtr executeVariable(const Token *tok, Data &data)
|
||||||
{
|
{
|
||||||
auto val = data.getValue(tok->varId(), tok->valueType());
|
auto val = data.getValue(tok->varId(), tok->valueType(), tok);
|
||||||
call(data.callbacks, tok, val);
|
call(data.callbacks, tok, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -429,6 +507,8 @@ static ExprEngine::ValuePtr executeExpression(const Token *tok, Data &data)
|
||||||
static void execute(const Token *start, const Token *end, Data &data)
|
static void execute(const Token *start, const Token *end, Data &data)
|
||||||
{
|
{
|
||||||
for (const Token *tok = start; tok != end; tok = tok->next()) {
|
for (const Token *tok = start; tok != end; tok = tok->next()) {
|
||||||
|
if (tok->str() == ";")
|
||||||
|
data.trackProgramState(tok);
|
||||||
if (tok->variable() && tok->variable()->nameToken() == tok) {
|
if (tok->variable() && tok->variable()->nameToken() == tok) {
|
||||||
if (tok->variable()->isArray() && tok->variable()->dimensions().size() == 1 && tok->variable()->dimensions()[0].known) {
|
if (tok->variable()->isArray() && tok->variable()->dimensions().size() == 1 && tok->variable()->dimensions()[0].known) {
|
||||||
data.memory[tok->varId()] = std::make_shared<ExprEngine::ArrayValue>(data.getNewSymbolName(), tok->variable()->dimension(0));
|
data.memory[tok->varId()] = std::make_shared<ExprEngine::ArrayValue>(data.getNewSymbolName(), tok->variable()->dimension(0));
|
||||||
|
@ -504,16 +584,23 @@ void ExprEngine::executeFunction(const Scope *functionScope, const Tokenizer *to
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int symbolValueIndex = 0;
|
int symbolValueIndex = 0;
|
||||||
Data data(&symbolValueIndex, tokenizer, settings, callbacks);
|
TrackExecution trackExecution;
|
||||||
data.printMemory();
|
Data data(&symbolValueIndex, tokenizer, settings, callbacks, &trackExecution);
|
||||||
|
|
||||||
for (const Variable &arg : function->argumentList) {
|
for (const Variable &arg : function->argumentList) {
|
||||||
ValuePtr val = createVariableValue(arg, data);
|
ValuePtr val = createVariableValue(arg, data);
|
||||||
if (val)
|
if (val) {
|
||||||
|
data.trackAssignment(arg.nameToken(), val);
|
||||||
data.memory[arg.declarationId()] = val;
|
data.memory[arg.declarationId()] = val;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
execute(functionScope->bodyStart, functionScope->bodyEnd, data);
|
execute(functionScope->bodyStart, functionScope->bodyEnd, data);
|
||||||
|
|
||||||
|
if (settings->verification) {
|
||||||
|
// TODO generate better output!!
|
||||||
|
trackExecution.print();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings)
|
void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings)
|
||||||
|
|
Loading…
Reference in New Issue