diff --git a/lib/exprengine.cpp b/lib/exprengine.cpp index 2aecdd521..1966bb054 100644 --- a/lib/exprengine.cpp +++ b/lib/exprengine.cpp @@ -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(data.getNewSymbolName(), std::make_shared()); - 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(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(data.getNewSymbolName(), structValue, true, false); + } return ExprEngine::ValuePtr(); } diff --git a/lib/exprengine.h b/lib/exprengine.h index 32cd0d17d..df7962ed9 100644 --- a/lib/exprengine.h +++ b/lib/exprengine.h @@ -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 { diff --git a/test/testexprengine.cpp b/test/testexprengine.cpp index 6eb8bc2d5..ba50d710d 100644 --- a/test/testexprengine.cpp +++ b/test/testexprengine.cpp @@ -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 ptr) { x = ptr; }", "ptr")); } void argStruct() {