ExprEngine: Better handling of pointers

This commit is contained in:
Daniel Marjamäki 2019-09-22 10:56:49 +02:00
parent 6c9839a585
commit ec4b7c1f4b
3 changed files with 49 additions and 12 deletions

View File

@ -269,6 +269,18 @@ std::string ExprEngine::ArrayValue::getRange() const
return r.str();
}
std::string ExprEngine::PointerValue::getRange() const
{
std::string r;
if (data)
r = "->" + data->getRange();
if (null)
r += std::string(r.empty() ? "" : ",") + "null";
if (uninitData)
r += std::string(r.empty() ? "" : ",") + "->?";
return r;
}
std::string ExprEngine::BinOpResult::getRange() const
{
int128_t minValue, maxValue;
@ -670,14 +682,28 @@ static ExprEngine::ValuePtr createStructVal(const Scope *structScope, Data &data
static ExprEngine::ValuePtr createVariableValue(const Variable &var, Data &data)
{
if (!var.nameToken() || !var.valueType())
if (!var.nameToken())
return ExprEngine::ValuePtr();
if (var.valueType()->pointer > 0)
return std::make_shared<ExprEngine::PointerValue>(data.getNewSymbolName(), std::make_shared<ExprEngine::UninitValue>());
if (var.valueType()->isIntegral())
return getValueRangeFromValueType(data.getNewSymbolName(), var.valueType(), *data.settings);
if (var.valueType()->type == ValueType::Type::RECORD)
return createStructVal(var.valueType()->typeScope, data);
const ValueType *valueType = var.valueType();
if (!valueType || valueType->type == ValueType::Type::UNKNOWN_TYPE)
valueType = var.nameToken()->valueType();
if (!valueType || valueType->type == ValueType::Type::UNKNOWN_TYPE)
return ExprEngine::ValuePtr();
if (valueType->pointer > 0) {
ValueType vt(*valueType);
vt.pointer = 0;
auto intRange = getValueRangeFromValueType(data.getNewSymbolName(), &vt, *data.settings);
return std::make_shared<ExprEngine::PointerValue>(data.getNewSymbolName(), intRange, true, true);
}
if (valueType->isIntegral())
return getValueRangeFromValueType(data.getNewSymbolName(), valueType, *data.settings);
if (valueType->type == ValueType::Type::RECORD)
return createStructVal(valueType->typeScope, data);
if (valueType->smartPointerType) {
auto structValue = createStructVal(valueType->smartPointerType->classScope, data);
return std::make_shared<ExprEngine::PointerValue>(data.getNewSymbolName(), structValue, true, false);
}
return ExprEngine::ValuePtr();
}

View File

@ -108,14 +108,19 @@ namespace ExprEngine {
class PointerValue: public Value {
public:
PointerValue(const std::string &name, ValuePtr data) : Value(name), data(data) {}
PointerValue(const std::string &name, ValuePtr data, bool null, bool uninitData)
: Value(name)
, data(data)
, null(null)
, uninitData(uninitData) {
}
ValueType type() const override {
return ValueType::PointerValue;
}
std::string getRange() const override {
return "*" + data->getRange();
}
std::string getRange() const override;
ValuePtr data;
bool null;
bool uninitData;
};
class ArrayValue: public Value {

View File

@ -30,6 +30,7 @@ public:
private:
void run() OVERRIDE {
TEST_CASE(argPointer);
TEST_CASE(argSmartPointer);
TEST_CASE(argStruct);
TEST_CASE(expr1);
@ -61,6 +62,7 @@ private:
std::string getRange(const char code[], const std::string &str) {
Settings settings;
settings.platform(cppcheck::Platform::Unix64);
settings.library.smartPointers.insert("std::shared_ptr");
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
@ -79,7 +81,11 @@ private:
}
void argPointer() {
ASSERT_EQUALS("?", getRange("void f(unsigned char *p) { a = *p; }", "*p"));
ASSERT_EQUALS("->0:255,null,->?", getRange("void f(unsigned char *p) { a = *p; }", "p"));
}
void argSmartPointer() {
ASSERT_EQUALS("->$1,null", getRange("struct S { int x; }; void f(std::shared_ptr<S> ptr) { x = ptr; }", "ptr"));
}
void argStruct() {