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() == "[") {
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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]"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue