ExprEngine: handling array initialization with string literal
This commit is contained in:
parent
d6a70d27c7
commit
3d0d3ec4c5
|
@ -411,8 +411,22 @@ static ExprEngine::ValuePtr executeAssign(const Token *tok, Data &data)
|
||||||
} else if (lhsToken->str() == "[") {
|
} else if (lhsToken->str() == "[") {
|
||||||
auto arrayValue = data.getArrayValue(lhsToken->astOperand1());
|
auto arrayValue = data.getArrayValue(lhsToken->astOperand1());
|
||||||
if (arrayValue) {
|
if (arrayValue) {
|
||||||
auto indexValue = executeExpression(lhsToken->astOperand2(), data);
|
// Is it array initialization?
|
||||||
arrayValue->assign(indexValue, rhsValue);
|
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("*")) {
|
} else if (lhsToken->isUnaryOp("*")) {
|
||||||
auto pval = executeExpression(lhsToken->astOperand1(), data);
|
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);
|
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)
|
static ExprEngine::ValuePtr executeExpression(const Token *tok, Data &data)
|
||||||
{
|
{
|
||||||
if (tok->str() == "return")
|
if (tok->str() == "return")
|
||||||
|
@ -540,6 +560,9 @@ static ExprEngine::ValuePtr executeExpression(const Token *tok, Data &data)
|
||||||
if (tok->isNumber())
|
if (tok->isNumber())
|
||||||
return executeNumber(tok);
|
return executeNumber(tok);
|
||||||
|
|
||||||
|
if (tok->tokType() == Token::Type::eString)
|
||||||
|
return executeStringLiteral(tok, data);
|
||||||
|
|
||||||
return ExprEngine::ValuePtr();
|
return ExprEngine::ValuePtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace ExprEngine {
|
||||||
std::string str(int128_t);
|
std::string str(int128_t);
|
||||||
|
|
||||||
// TODO we need to handle floats, containers, pointers, aliases and structs and stuff
|
// 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;
|
class Value;
|
||||||
typedef std::shared_ptr<Value> ValuePtr;
|
typedef std::shared_ptr<Value> ValuePtr;
|
||||||
|
@ -139,6 +139,26 @@ namespace ExprEngine {
|
||||||
std::vector<ValuePtr> data;
|
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 {
|
class StructValue: public Value {
|
||||||
public:
|
public:
|
||||||
explicit StructValue(const std::string &name) : Value(name) {}
|
explicit StructValue(const std::string &name) : Value(name) {}
|
||||||
|
|
|
@ -49,6 +49,7 @@ private:
|
||||||
TEST_CASE(ifelse1);
|
TEST_CASE(ifelse1);
|
||||||
|
|
||||||
TEST_CASE(localArray1);
|
TEST_CASE(localArray1);
|
||||||
|
TEST_CASE(localArray2);
|
||||||
TEST_CASE(localArrayUninit);
|
TEST_CASE(localArrayUninit);
|
||||||
|
|
||||||
TEST_CASE(pointerAlias1);
|
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]"));
|
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() {
|
void localArrayUninit() {
|
||||||
ASSERT_EQUALS("?", getRange("inf f() { int arr[10]; return arr[4]; }", "arr[4]"));
|
ASSERT_EQUALS("?", getRange("inf f() { int arr[10]; return arr[4]; }", "arr[4]"));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue