[SMTChecker] Added support for struct constructor.

This commit is contained in:
Martin Blicha
2020-11-23 13:45:17 +01:00
parent b62de4f16d
commit 80d743426f
18 changed files with 165 additions and 52 deletions
+14 -5
View File
@@ -622,11 +622,7 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall)
createExpr(_funCall);
if (functionCallKind == FunctionCallKind::StructConstructorCall)
{
m_errorReporter.warning(
4639_error,
_funCall.location(),
"Assertion checker does not yet implement this expression."
);
visitStructConstructorCall(_funCall);
return;
}
@@ -861,6 +857,12 @@ void SMTEncoder::endVisit(Identifier const& _identifier)
defineExpr(_identifier, m_context.state().thisAddress());
m_uninterpretedTerms.insert(&_identifier);
}
// Ignore struct type identifiers in struct constructor calls
else if (
auto typetype = dynamic_cast<TypeType const*>(_identifier.annotation().type);
typetype && typetype->actualType()->category() == Type::Category::Struct
)
return;
// Ignore the builtin abi, it is handled in FunctionCall.
// TODO: ignore MagicType in general (abi, block, msg, tx, type)
else if (auto magicType = dynamic_cast<MagicType const*>(_identifier.annotation().type); magicType && magicType->kind() == MagicType::Kind::ABI)
@@ -1018,6 +1020,13 @@ void SMTEncoder::visitFunctionIdentifier(Identifier const& _identifier)
}
}
void SMTEncoder::visitStructConstructorCall(FunctionCall const& _funCall)
{
solAssert(*_funCall.annotation().kind == FunctionCallKind::StructConstructorCall, "");
auto& structSymbolicVar = dynamic_cast<smt::SymbolicStructVariable&>(*m_context.expression(_funCall));
structSymbolicVar.assignAllMembers(applyMap(_funCall.sortedArguments(), [this](auto const& arg) { return expr(*arg); }));
}
void SMTEncoder::endVisit(Literal const& _literal)
{
solAssert(_literal.annotation().type, "Expected type for AST node");
+1
View File
@@ -151,6 +151,7 @@ protected:
virtual void visitAddMulMod(FunctionCall const& _funCall);
void visitObjectCreation(FunctionCall const& _funCall);
void visitTypeConversion(FunctionCall const& _funCall);
void visitStructConstructorCall(FunctionCall const& _funCall);
void visitFunctionIdentifier(Identifier const& _identifier);
/// Encodes a modifier or function body according to the modifier
+16 -1
View File
@@ -360,7 +360,7 @@ SymbolicStructVariable::SymbolicStructVariable(
}
}
smtutil::Expression SymbolicStructVariable::member(string const& _member)
smtutil::Expression SymbolicStructVariable::member(string const& _member) const
{
return smtutil::Expression::tuple_get(currentValue(), m_memberIndices.at(_member));
}
@@ -385,3 +385,18 @@ smtutil::Expression SymbolicStructVariable::assignMember(string const& _member,
return currentValue();
}
smtutil::Expression SymbolicStructVariable::assignAllMembers(vector<smtutil::Expression> const& _memberValues)
{
auto structType = dynamic_cast<StructType const*>(m_type);
solAssert(structType, "");
auto const& structDef = structType->structDefinition();
auto const& structMembers = structDef.members();
solAssert(_memberValues.size() == structMembers.size(), "");
increaseIndex();
for (unsigned i = 0; i < _memberValues.size(); ++i)
m_context.addAssertion(_memberValues[i] == member(structMembers[i]->name()));
return currentValue();
}
+5 -1
View File
@@ -282,12 +282,16 @@ public:
);
/// @returns the symbolic expression representing _member.
smtutil::Expression member(std::string const& _member);
smtutil::Expression member(std::string const& _member) const;
/// @returns the symbolic expression representing this struct
/// with field _member updated.
smtutil::Expression assignMember(std::string const& _member, smtutil::Expression const& _memberValue);
/// @returns the symbolic expression representing this struct
/// with all fields updated with the given values.
smtutil::Expression assignAllMembers(std::vector<smtutil::Expression> const& _memberValues);
private:
std::map<std::string, unsigned> m_memberIndices;
};