ExprEngine: Better handling of pointers
This commit is contained in:
parent
6c9839a585
commit
ec4b7c1f4b
|
@ -269,6 +269,18 @@ std::string ExprEngine::ArrayValue::getRange() const
|
||||||
return r.str();
|
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
|
std::string ExprEngine::BinOpResult::getRange() const
|
||||||
{
|
{
|
||||||
int128_t minValue, maxValue;
|
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)
|
static ExprEngine::ValuePtr createVariableValue(const Variable &var, Data &data)
|
||||||
{
|
{
|
||||||
if (!var.nameToken() || !var.valueType())
|
if (!var.nameToken())
|
||||||
return ExprEngine::ValuePtr();
|
return ExprEngine::ValuePtr();
|
||||||
if (var.valueType()->pointer > 0)
|
const ValueType *valueType = var.valueType();
|
||||||
return std::make_shared<ExprEngine::PointerValue>(data.getNewSymbolName(), std::make_shared<ExprEngine::UninitValue>());
|
if (!valueType || valueType->type == ValueType::Type::UNKNOWN_TYPE)
|
||||||
if (var.valueType()->isIntegral())
|
valueType = var.nameToken()->valueType();
|
||||||
return getValueRangeFromValueType(data.getNewSymbolName(), var.valueType(), *data.settings);
|
if (!valueType || valueType->type == ValueType::Type::UNKNOWN_TYPE)
|
||||||
if (var.valueType()->type == ValueType::Type::RECORD)
|
return ExprEngine::ValuePtr();
|
||||||
return createStructVal(var.valueType()->typeScope, data);
|
|
||||||
|
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();
|
return ExprEngine::ValuePtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,14 +108,19 @@ namespace ExprEngine {
|
||||||
|
|
||||||
class PointerValue: public Value {
|
class PointerValue: public Value {
|
||||||
public:
|
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 {
|
ValueType type() const override {
|
||||||
return ValueType::PointerValue;
|
return ValueType::PointerValue;
|
||||||
}
|
}
|
||||||
std::string getRange() const override {
|
std::string getRange() const override;
|
||||||
return "*" + data->getRange();
|
|
||||||
}
|
|
||||||
ValuePtr data;
|
ValuePtr data;
|
||||||
|
bool null;
|
||||||
|
bool uninitData;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArrayValue: public Value {
|
class ArrayValue: public Value {
|
||||||
|
|
|
@ -30,6 +30,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void run() OVERRIDE {
|
void run() OVERRIDE {
|
||||||
TEST_CASE(argPointer);
|
TEST_CASE(argPointer);
|
||||||
|
TEST_CASE(argSmartPointer);
|
||||||
TEST_CASE(argStruct);
|
TEST_CASE(argStruct);
|
||||||
|
|
||||||
TEST_CASE(expr1);
|
TEST_CASE(expr1);
|
||||||
|
@ -61,6 +62,7 @@ private:
|
||||||
std::string getRange(const char code[], const std::string &str) {
|
std::string getRange(const char code[], const std::string &str) {
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.platform(cppcheck::Platform::Unix64);
|
settings.platform(cppcheck::Platform::Unix64);
|
||||||
|
settings.library.smartPointers.insert("std::shared_ptr");
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize(istr, "test.cpp");
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
|
@ -79,7 +81,11 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void argPointer() {
|
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() {
|
void argStruct() {
|
||||||
|
|
Loading…
Reference in New Issue