ExprEngine: handling array initialization with string literal

This commit is contained in:
Daniel Marjamäki 2019-09-21 11:36:34 +02:00
parent d6a70d27c7
commit 3d0d3ec4c5
3 changed files with 51 additions and 3 deletions

View File

@ -411,8 +411,22 @@ static ExprEngine::ValuePtr executeAssign(const Token *tok, Data &data)
} else if (lhsToken->str() == "[") {
auto arrayValue = data.getArrayValue(lhsToken->astOperand1());
if (arrayValue) {
auto indexValue = executeExpression(lhsToken->astOperand2(), data);
arrayValue->assign(indexValue, rhsValue);
// Is it array initialization?
const Token *arrayInit = lhsToken->astOperand1();
if (arrayInit && arrayInit->variable() && arrayInit->variable()->nameToken() == arrayInit) {
if (auto strval = std::dynamic_pointer_cast<ExprEngine::StringLiteralValue>(rhsValue)) {
for (size_t i = 0; i < strval->size(); ++i) {
uint8_t c = strval->string[i];
arrayValue->data[i] = std::make_shared<ExprEngine::IntRange>(std::to_string(int(c)),c,c);
}
auto v0 = std::make_shared<ExprEngine::IntRange>("0",0,0);
for (size_t i = strval->size(); i < arrayValue->data.size(); ++i)
arrayValue->data[i] = v0;
}
} else {
auto indexValue = executeExpression(lhsToken->astOperand2(), data);
arrayValue->assign(indexValue, rhsValue);
}
}
} else if (lhsToken->isUnaryOp("*")) {
auto pval = executeExpression(lhsToken->astOperand1(), data);
@ -508,6 +522,12 @@ static ExprEngine::ValuePtr executeNumber(const Token *tok)
return std::make_shared<ExprEngine::IntRange>(tok->str(), value, value);
}
static ExprEngine::ValuePtr executeStringLiteral(const Token *tok, Data &data)
{
std::string s = tok->str();
return std::make_shared<ExprEngine::StringLiteralValue>(data.getNewSymbolName(), s.substr(1, s.size()-2));
}
static ExprEngine::ValuePtr executeExpression(const Token *tok, Data &data)
{
if (tok->str() == "return")
@ -540,6 +560,9 @@ static ExprEngine::ValuePtr executeExpression(const Token *tok, Data &data)
if (tok->isNumber())
return executeNumber(tok);
if (tok->tokType() == Token::Type::eString)
return executeStringLiteral(tok, data);
return ExprEngine::ValuePtr();
}

View File

@ -52,7 +52,7 @@ namespace ExprEngine {
std::string str(int128_t);
// TODO we need to handle floats, containers, pointers, aliases and structs and stuff
enum class ValueType { UninitValue, IntRange, PointerValue, ArrayValue, StructValue, AddressOfValue, BinOpResult };
enum class ValueType { UninitValue, IntRange, PointerValue, ArrayValue, StringLiteralValue, StructValue, AddressOfValue, BinOpResult };
class Value;
typedef std::shared_ptr<Value> ValuePtr;
@ -139,6 +139,26 @@ namespace ExprEngine {
std::vector<ValuePtr> data;
};
class StringLiteralValue: public Value {
public:
StringLiteralValue(const std::string &name, const std::string &s)
: Value(name)
, string(s) {
}
ValueType type() const override {
return ValueType::StringLiteralValue;
}
std::string getRange() const override {
return "\"" + string + "\"";
}
int size() const {
return string.size();
}
const std::string string;
};
class StructValue: public Value {
public:
explicit StructValue(const std::string &name) : Value(name) {}

View File

@ -49,6 +49,7 @@ private:
TEST_CASE(ifelse1);
TEST_CASE(localArray1);
TEST_CASE(localArray2);
TEST_CASE(localArrayUninit);
TEST_CASE(pointerAlias1);
@ -137,6 +138,10 @@ private:
ASSERT_EQUALS("[5:5]", getRange("inf f() { int arr[10]; arr[4] = 5; return arr[4]; }", "arr[4]"));
}
void localArray2() {
ASSERT_EQUALS("[0:0]", getRange("inf f() { char arr[10] = \"\"; return arr[4]; }", "arr[4]"));
}
void localArrayUninit() {
ASSERT_EQUALS("?", getRange("inf f() { int arr[10]; return arr[4]; }", "arr[4]"));
}