Make recursive structs unsupported

This commit is contained in:
Leonardo Alt 2020-08-27 15:16:02 +02:00
parent 3093648c05
commit 7b3cd019d4
5 changed files with 134 additions and 127 deletions

View File

@ -580,7 +580,7 @@ pair<vector<smtutil::Expression>, vector<string>> BMC::modelExpressions()
auto const& type = var.second->type(); auto const& type = var.second->type();
if ( if (
type->isValueType() && type->isValueType() &&
smt::smtKind(type->category()) != smtutil::Kind::Function smt::smtKind(*type) != smtutil::Kind::Function
) )
{ {
expressionsToEvaluate.emplace_back(var.second->currentValue()); expressionsToEvaluate.emplace_back(var.second->currentValue());

View File

@ -378,7 +378,7 @@ void SMTEncoder::endVisit(Assignment const& _assignment)
"Assertion checker does not yet implement this assignment operator." "Assertion checker does not yet implement this assignment operator."
); );
} }
else if (!smt::isSupportedType(_assignment.annotation().type->category())) else if (!smt::isSupportedType(*_assignment.annotation().type))
{ {
// Give it a new index anyway to keep the SSA scheme sound. // Give it a new index anyway to keep the SSA scheme sound.
@ -462,20 +462,19 @@ void SMTEncoder::endVisit(UnaryOperation const& _op)
createExpr(_op); createExpr(_op);
auto const* subExpr = innermostTuple(_op.subExpression()); auto const* subExpr = innermostTuple(_op.subExpression());
auto type = _op.annotation().type;
switch (_op.getOperator()) switch (_op.getOperator())
{ {
case Token::Not: // ! case Token::Not: // !
{ {
solAssert(smt::isBool(_op.annotation().type->category()), ""); solAssert(smt::isBool(*type), "");
defineExpr(_op, !expr(*subExpr)); defineExpr(_op, !expr(*subExpr));
break; break;
} }
case Token::Inc: // ++ (pre- or postfix) case Token::Inc: // ++ (pre- or postfix)
case Token::Dec: // -- (pre- or postfix) case Token::Dec: // -- (pre- or postfix)
{ {
auto cat = _op.annotation().type->category(); solAssert(smt::isInteger(*type) || smt::isFixedPoint(*type), "");
solAssert(smt::isInteger(cat) || smt::isFixedPoint(cat), "");
solAssert(subExpr->annotation().willBeWrittenTo, ""); solAssert(subExpr->annotation().willBeWrittenTo, "");
if (auto identifier = dynamic_cast<Identifier const*>(subExpr)) if (auto identifier = dynamic_cast<Identifier const*>(subExpr))
{ {
@ -486,7 +485,10 @@ void SMTEncoder::endVisit(UnaryOperation const& _op)
defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue); defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue);
assignment(*decl, newValue); assignment(*decl, newValue);
} }
else if (dynamic_cast<IndexAccess const*>(subExpr)) else if (
dynamic_cast<IndexAccess const*>(&_op.subExpression()) ||
dynamic_cast<MemberAccess const*>(&_op.subExpression())
)
{ {
auto innerValue = expr(*subExpr); auto innerValue = expr(*subExpr);
auto newValue = _op.getOperator() == Token::Inc ? innerValue + 1 : innerValue - 1; auto newValue = _op.getOperator() == Token::Inc ? innerValue + 1 : innerValue - 1;
@ -824,11 +826,11 @@ void SMTEncoder::endVisit(Literal const& _literal)
{ {
solAssert(_literal.annotation().type, "Expected type for AST node"); solAssert(_literal.annotation().type, "Expected type for AST node");
Type const& type = *_literal.annotation().type; Type const& type = *_literal.annotation().type;
if (smt::isNumber(type.category())) if (smt::isNumber(type))
defineExpr(_literal, smtutil::Expression(type.literalValue(&_literal))); defineExpr(_literal, smtutil::Expression(type.literalValue(&_literal)));
else if (smt::isBool(type.category())) else if (smt::isBool(type))
defineExpr(_literal, smtutil::Expression(_literal.token() == Token::TrueLiteral ? true : false)); defineExpr(_literal, smtutil::Expression(_literal.token() == Token::TrueLiteral ? true : false));
else if (smt::isStringLiteral(type.category())) else if (smt::isStringLiteral(type))
createExpr(_literal); createExpr(_literal);
else else
{ {
@ -891,7 +893,7 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess)
defineGlobalVariable(accessedName + "." + _memberAccess.memberName(), _memberAccess); defineGlobalVariable(accessedName + "." + _memberAccess.memberName(), _memberAccess);
return false; return false;
} }
else if (exprType->category() == Type::Category::Struct) else if (smt::isNonRecursiveStruct(*exprType))
{ {
_memberAccess.expression().accept(*this); _memberAccess.expression().accept(*this);
auto const& symbStruct = dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(_memberAccess.expression())); auto const& symbStruct = dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(_memberAccess.expression()));
@ -1034,6 +1036,20 @@ void SMTEncoder::indexOrMemberAssignment(Expression const& _expr, smtutil::Expre
auto const& base = memberAccess->expression(); auto const& base = memberAccess->expression();
if (dynamic_cast<Identifier const*>(&base)) if (dynamic_cast<Identifier const*>(&base))
base.accept(*this); base.accept(*this);
if (
auto const* structType = dynamic_cast<StructType const*>(base.annotation().type);
structType && structType->recursive()
)
{
m_errorReporter.warning(
4375_error,
memberAccess->location(),
"Assertion checker does not support recursive structs."
);
return;
}
auto symbStruct = dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(base)); auto symbStruct = dynamic_pointer_cast<smt::SymbolicStructVariable>(m_context.expression(base));
solAssert(symbStruct, ""); solAssert(symbStruct, "");
symbStruct->assignMember(memberAccess->memberName(), toStore); symbStruct->assignMember(memberAccess->memberName(), toStore);
@ -1186,7 +1202,7 @@ void SMTEncoder::defineGlobalVariable(string const& _name, Expression const& _ex
m_context.globalSymbol(_name)->increaseIndex(); m_context.globalSymbol(_name)->increaseIndex();
// The default behavior is not to increase the index since // The default behavior is not to increase the index since
// most of the global values stay the same throughout a tx. // most of the global values stay the same throughout a tx.
if (smt::isSupportedType(_expr.annotation().type->category())) if (smt::isSupportedType(*_expr.annotation().type))
defineExpr(_expr, m_context.globalSymbol(_name)->currentValue()); defineExpr(_expr, m_context.globalSymbol(_name)->currentValue());
} }
@ -1339,13 +1355,13 @@ void SMTEncoder::compareOperation(BinaryOperation const& _op)
{ {
auto const& commonType = _op.annotation().commonType; auto const& commonType = _op.annotation().commonType;
solAssert(commonType, ""); solAssert(commonType, "");
if (smt::isSupportedType(commonType->category())) if (smt::isSupportedType(*commonType))
{ {
smtutil::Expression left(expr(_op.leftExpression(), commonType)); smtutil::Expression left(expr(_op.leftExpression(), commonType));
smtutil::Expression right(expr(_op.rightExpression(), commonType)); smtutil::Expression right(expr(_op.rightExpression(), commonType));
Token op = _op.getOperator(); Token op = _op.getOperator();
shared_ptr<smtutil::Expression> value; shared_ptr<smtutil::Expression> value;
if (smt::isNumber(commonType->category())) if (smt::isNumber(*commonType))
{ {
value = make_shared<smtutil::Expression>( value = make_shared<smtutil::Expression>(
op == Token::Equal ? (left == right) : op == Token::Equal ? (left == right) :
@ -1358,7 +1374,7 @@ void SMTEncoder::compareOperation(BinaryOperation const& _op)
} }
else // Bool else // Bool
{ {
solUnimplementedAssert(smt::isBool(commonType->category()), "Operation not yet supported"); solUnimplementedAssert(smt::isBool(*commonType), "Operation not yet supported");
value = make_shared<smtutil::Expression>( value = make_shared<smtutil::Expression>(
op == Token::Equal ? (left == right) : op == Token::Equal ? (left == right) :
/*op == Token::NotEqual*/ (left != right) /*op == Token::NotEqual*/ (left != right)
@ -1464,7 +1480,7 @@ void SMTEncoder::assignment(
Expression const* left = innermostTuple(_left); Expression const* left = innermostTuple(_left);
if (!smt::isSupportedType(_type->category())) if (!smt::isSupportedType(*_type))
{ {
// Give it a new index anyway to keep the SSA scheme sound. // Give it a new index anyway to keep the SSA scheme sound.
if (auto varDecl = identifierToVariable(*left)) if (auto varDecl = identifierToVariable(*left))

View File

@ -33,7 +33,7 @@ namespace solidity::frontend::smt
SortPointer smtSort(frontend::Type const& _type) SortPointer smtSort(frontend::Type const& _type)
{ {
switch (smtKind(_type.category())) switch (smtKind(_type))
{ {
case Kind::Int: case Kind::Int:
if (auto const* intType = dynamic_cast<IntegerType const*>(&_type)) if (auto const* intType = dynamic_cast<IntegerType const*>(&_type))
@ -64,13 +64,13 @@ SortPointer smtSort(frontend::Type const& _type)
case Kind::Array: case Kind::Array:
{ {
shared_ptr<ArraySort> array; shared_ptr<ArraySort> array;
if (isMapping(_type.category())) if (isMapping(_type))
{ {
auto mapType = dynamic_cast<frontend::MappingType const*>(&_type); auto mapType = dynamic_cast<frontend::MappingType const*>(&_type);
solAssert(mapType, ""); solAssert(mapType, "");
array = make_shared<ArraySort>(smtSortAbstractFunction(*mapType->keyType()), smtSortAbstractFunction(*mapType->valueType())); array = make_shared<ArraySort>(smtSortAbstractFunction(*mapType->keyType()), smtSortAbstractFunction(*mapType->valueType()));
} }
else if (isStringLiteral(_type.category())) else if (isStringLiteral(_type))
{ {
auto stringLitType = dynamic_cast<frontend::StringLiteralType const*>(&_type); auto stringLitType = dynamic_cast<frontend::StringLiteralType const*>(&_type);
solAssert(stringLitType, ""); solAssert(stringLitType, "");
@ -144,6 +144,7 @@ SortPointer smtSort(frontend::Type const& _type)
} }
else if (auto const* structType = dynamic_cast<frontend::StructType const*>(&_type)) else if (auto const* structType = dynamic_cast<frontend::StructType const*>(&_type))
{ {
solAssert(!structType->recursive(), "");
auto const& structMembers = structType->structDefinition().members(); auto const& structMembers = structType->structDefinition().members();
for (auto member: structMembers) for (auto member: structMembers)
members.emplace_back(tupleName + "_accessor_" + member->name()); members.emplace_back(tupleName + "_accessor_" + member->name());
@ -173,7 +174,7 @@ vector<SortPointer> smtSort(vector<frontend::TypePointer> const& _types)
SortPointer smtSortAbstractFunction(frontend::Type const& _type) SortPointer smtSortAbstractFunction(frontend::Type const& _type)
{ {
if (isFunction(_type.category())) if (isFunction(_type))
return SortProvider::uintSort; return SortProvider::uintSort;
return smtSort(_type); return smtSort(_type);
} }
@ -189,36 +190,36 @@ vector<SortPointer> smtSortAbstractFunction(vector<frontend::TypePointer> const&
return sorts; return sorts;
} }
Kind smtKind(frontend::Type::Category _category) Kind smtKind(frontend::Type const& _type)
{ {
if (isNumber(_category)) if (isNumber(_type))
return Kind::Int; return Kind::Int;
else if (isBool(_category)) else if (isBool(_type))
return Kind::Bool; return Kind::Bool;
else if (isFunction(_category)) else if (isFunction(_type))
return Kind::Function; return Kind::Function;
else if (isMapping(_category) || isArray(_category)) else if (isMapping(_type) || isArray(_type))
return Kind::Array; return Kind::Array;
else if (isTuple(_category) || isStruct(_category)) else if (isTuple(_type) || isNonRecursiveStruct(_type))
return Kind::Tuple; return Kind::Tuple;
// Abstract case. // Abstract case.
return Kind::Int; return Kind::Int;
} }
bool isSupportedType(frontend::Type::Category _category) bool isSupportedType(frontend::Type const& _type)
{ {
return isNumber(_category) || return isNumber(_type) ||
isBool(_category) || isBool(_type) ||
isMapping(_category) || isMapping(_type) ||
isArray(_category) || isArray(_type) ||
isTuple(_category) || isTuple(_type) ||
isStruct(_category); isNonRecursiveStruct(_type);
} }
bool isSupportedTypeDeclaration(frontend::Type::Category _category) bool isSupportedTypeDeclaration(frontend::Type const& _type)
{ {
return isSupportedType(_category) || return isSupportedType(_type) ||
isFunction(_category); isFunction(_type);
} }
pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable( pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
@ -235,9 +236,9 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
abstract = true; abstract = true;
var = make_shared<SymbolicIntVariable>(frontend::TypeProvider::uint256(), type, _uniqueName, _context); var = make_shared<SymbolicIntVariable>(frontend::TypeProvider::uint256(), type, _uniqueName, _context);
} }
else if (isBool(_type.category())) else if (isBool(_type))
var = make_shared<SymbolicBoolVariable>(type, _uniqueName, _context); var = make_shared<SymbolicBoolVariable>(type, _uniqueName, _context);
else if (isFunction(_type.category())) else if (isFunction(_type))
{ {
auto const& fType = dynamic_cast<FunctionType const*>(type); auto const& fType = dynamic_cast<FunctionType const*>(type);
auto const& paramsIn = fType->parameterTypes(); auto const& paramsIn = fType->parameterTypes();
@ -260,21 +261,21 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
else else
var = make_shared<SymbolicFunctionVariable>(type, _uniqueName, _context); var = make_shared<SymbolicFunctionVariable>(type, _uniqueName, _context);
} }
else if (isInteger(_type.category())) else if (isInteger(_type))
var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context); var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
else if (isFixedPoint(_type.category())) else if (isFixedPoint(_type))
var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context); var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
else if (isFixedBytes(_type.category())) else if (isFixedBytes(_type))
{ {
auto fixedBytesType = dynamic_cast<frontend::FixedBytesType const*>(type); auto fixedBytesType = dynamic_cast<frontend::FixedBytesType const*>(type);
solAssert(fixedBytesType, ""); solAssert(fixedBytesType, "");
var = make_shared<SymbolicFixedBytesVariable>(type, fixedBytesType->numBytes(), _uniqueName, _context); var = make_shared<SymbolicFixedBytesVariable>(type, fixedBytesType->numBytes(), _uniqueName, _context);
} }
else if (isAddress(_type.category()) || isContract(_type.category())) else if (isAddress(_type) || isContract(_type))
var = make_shared<SymbolicAddressVariable>(_uniqueName, _context); var = make_shared<SymbolicAddressVariable>(_uniqueName, _context);
else if (isEnum(_type.category())) else if (isEnum(_type))
var = make_shared<SymbolicEnumVariable>(type, _uniqueName, _context); var = make_shared<SymbolicEnumVariable>(type, _uniqueName, _context);
else if (isRational(_type.category())) else if (isRational(_type))
{ {
auto rational = dynamic_cast<frontend::RationalNumberType const*>(&_type); auto rational = dynamic_cast<frontend::RationalNumberType const*>(&_type);
solAssert(rational, ""); solAssert(rational, "");
@ -283,113 +284,104 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable(
else else
var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context); var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context);
} }
else if (isMapping(_type.category()) || isArray(_type.category())) else if (isMapping(_type) || isArray(_type))
var = make_shared<SymbolicArrayVariable>(type, type, _uniqueName, _context); var = make_shared<SymbolicArrayVariable>(type, type, _uniqueName, _context);
else if (isTuple(_type.category())) else if (isTuple(_type))
var = make_shared<SymbolicTupleVariable>(type, _uniqueName, _context); var = make_shared<SymbolicTupleVariable>(type, _uniqueName, _context);
else if (isStringLiteral(_type.category())) else if (isStringLiteral(_type))
{ {
auto stringType = TypeProvider::stringMemory(); auto stringType = TypeProvider::stringMemory();
var = make_shared<SymbolicArrayVariable>(stringType, type, _uniqueName, _context); var = make_shared<SymbolicArrayVariable>(stringType, type, _uniqueName, _context);
} }
else if (isStruct(_type.category())) else if (isNonRecursiveStruct(_type))
var = make_shared<SymbolicStructVariable>(type, _uniqueName, _context); var = make_shared<SymbolicStructVariable>(type, _uniqueName, _context);
else else
solAssert(false, ""); solAssert(false, "");
return make_pair(abstract, var); return make_pair(abstract, var);
} }
bool isSupportedType(frontend::Type const& _type) bool isInteger(frontend::Type const& _type)
{ {
return isSupportedType(_type.category()); return _type.category() == frontend::Type::Category::Integer;
} }
bool isSupportedTypeDeclaration(frontend::Type const& _type) bool isFixedPoint(frontend::Type const& _type)
{ {
return isSupportedTypeDeclaration(_type.category()); return _type.category() == frontend::Type::Category::FixedPoint;
} }
bool isInteger(frontend::Type::Category _category) bool isRational(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::Integer; return _type.category() == frontend::Type::Category::RationalNumber;
} }
bool isFixedPoint(frontend::Type::Category _category) bool isFixedBytes(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::FixedPoint; return _type.category() == frontend::Type::Category::FixedBytes;
} }
bool isRational(frontend::Type::Category _category) bool isAddress(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::RationalNumber; return _type.category() == frontend::Type::Category::Address;
} }
bool isFixedBytes(frontend::Type::Category _category) bool isContract(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::FixedBytes; return _type.category() == frontend::Type::Category::Contract;
} }
bool isAddress(frontend::Type::Category _category) bool isEnum(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::Address; return _type.category() == frontend::Type::Category::Enum;
} }
bool isContract(frontend::Type::Category _category) bool isNumber(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::Contract; return isInteger(_type) ||
isFixedPoint(_type) ||
isRational(_type) ||
isFixedBytes(_type) ||
isAddress(_type) ||
isContract(_type) ||
isEnum(_type);
} }
bool isEnum(frontend::Type::Category _category) bool isBool(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::Enum; return _type.category() == frontend::Type::Category::Bool;
} }
bool isNumber(frontend::Type::Category _category) bool isFunction(frontend::Type const& _type)
{ {
return isInteger(_category) || return _type.category() == frontend::Type::Category::Function;
isFixedPoint(_category) ||
isRational(_category) ||
isFixedBytes(_category) ||
isAddress(_category) ||
isContract(_category) ||
isEnum(_category);
} }
bool isBool(frontend::Type::Category _category) bool isMapping(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::Bool; return _type.category() == frontend::Type::Category::Mapping;
} }
bool isFunction(frontend::Type::Category _category) bool isArray(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::Function; return _type.category() == frontend::Type::Category::Array ||
_type.category() == frontend::Type::Category::StringLiteral ||
_type.category() == frontend::Type::Category::ArraySlice;
} }
bool isMapping(frontend::Type::Category _category) bool isTuple(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::Mapping; return _type.category() == frontend::Type::Category::Tuple;
} }
bool isArray(frontend::Type::Category _category) bool isStringLiteral(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::Array || return _type.category() == frontend::Type::Category::StringLiteral;
_category == frontend::Type::Category::StringLiteral ||
_category == frontend::Type::Category::ArraySlice;
} }
bool isTuple(frontend::Type::Category _category) bool isNonRecursiveStruct(frontend::Type const& _type)
{ {
return _category == frontend::Type::Category::Tuple; auto structType = dynamic_cast<StructType const*>(&_type);
} return structType && !structType->recursive();
bool isStringLiteral(frontend::Type::Category _category)
{
return _category == frontend::Type::Category::StringLiteral;
}
bool isStruct(frontend::Type::Category _category)
{
return _category == frontend::Type::Category::Struct;
} }
smtutil::Expression minValue(frontend::IntegerType const& _type) smtutil::Expression minValue(frontend::IntegerType const& _type)
@ -416,13 +408,13 @@ void setSymbolicZeroValue(smtutil::Expression _expr, frontend::TypePointer const
smtutil::Expression zeroValue(frontend::TypePointer const& _type) smtutil::Expression zeroValue(frontend::TypePointer const& _type)
{ {
solAssert(_type, ""); solAssert(_type, "");
if (isSupportedType(_type->category())) if (isSupportedType(*_type))
{ {
if (isNumber(_type->category())) if (isNumber(*_type))
return 0; return 0;
if (isBool(_type->category())) if (isBool(*_type))
return smtutil::Expression(false); return smtutil::Expression(false);
if (isArray(_type->category()) || isMapping(_type->category())) if (isArray(*_type) || isMapping(*_type))
{ {
auto tupleSort = dynamic_pointer_cast<TupleSort>(smtSort(*_type)); auto tupleSort = dynamic_pointer_cast<TupleSort>(smtSort(*_type));
solAssert(tupleSort, ""); solAssert(tupleSort, "");
@ -448,10 +440,9 @@ smtutil::Expression zeroValue(frontend::TypePointer const& _type)
); );
} }
if (isStruct(_type->category())) if (isNonRecursiveStruct(*_type))
{ {
auto const* structType = dynamic_cast<StructType const*>(_type); auto const* structType = dynamic_cast<StructType const*>(_type);
solAssert(structType, "");
auto structSort = dynamic_pointer_cast<TupleSort>(smtSort(*_type)); auto structSort = dynamic_pointer_cast<TupleSort>(smtSort(*_type));
return smtutil::Expression::tuple_constructor( return smtutil::Expression::tuple_constructor(
smtutil::Expression(make_shared<SortSort>(structSort), structSort->name), smtutil::Expression(make_shared<SortSort>(structSort), structSort->name),
@ -487,14 +478,14 @@ void setSymbolicUnknownValue(SymbolicVariable const& _variable, EncodingContext&
void setSymbolicUnknownValue(smtutil::Expression _expr, frontend::TypePointer const& _type, EncodingContext& _context) void setSymbolicUnknownValue(smtutil::Expression _expr, frontend::TypePointer const& _type, EncodingContext& _context)
{ {
solAssert(_type, ""); solAssert(_type, "");
if (isEnum(_type->category())) if (isEnum(*_type))
{ {
auto enumType = dynamic_cast<frontend::EnumType const*>(_type); auto enumType = dynamic_cast<frontend::EnumType const*>(_type);
solAssert(enumType, ""); solAssert(enumType, "");
_context.addAssertion(_expr >= 0); _context.addAssertion(_expr >= 0);
_context.addAssertion(_expr < enumType->numberOfMembers()); _context.addAssertion(_expr < enumType->numberOfMembers());
} }
else if (isInteger(_type->category())) else if (isInteger(*_type))
{ {
auto intType = dynamic_cast<frontend::IntegerType const*>(_type); auto intType = dynamic_cast<frontend::IntegerType const*>(_type);
solAssert(intType, ""); solAssert(intType, "");

View File

@ -34,30 +34,30 @@ std::vector<smtutil::SortPointer> smtSort(std::vector<frontend::TypePointer> con
smtutil::SortPointer smtSortAbstractFunction(frontend::Type const& _type); smtutil::SortPointer smtSortAbstractFunction(frontend::Type const& _type);
std::vector<smtutil::SortPointer> smtSortAbstractFunction(std::vector<frontend::TypePointer> const& _types); std::vector<smtutil::SortPointer> smtSortAbstractFunction(std::vector<frontend::TypePointer> const& _types);
/// Returns the SMT kind that models the Solidity type type category _category. /// Returns the SMT kind that models the Solidity type type category _category.
smtutil::Kind smtKind(frontend::Type::Category _category); smtutil::Kind smtKind(frontend::Type const& _type);
/// Returns true if type is fully supported (declaration and operations). /// Returns true if type is fully supported (declaration and operations).
bool isSupportedType(frontend::Type::Category _category); bool isSupportedType(frontend::Type const& _type);
bool isSupportedType(frontend::Type const& _type); bool isSupportedType(frontend::Type const& _type);
/// Returns true if type is partially supported (declaration). /// Returns true if type is partially supported (declaration).
bool isSupportedTypeDeclaration(frontend::Type::Category _category); bool isSupportedTypeDeclaration(frontend::Type const& _type);
bool isSupportedTypeDeclaration(frontend::Type const& _type); bool isSupportedTypeDeclaration(frontend::Type const& _type);
bool isInteger(frontend::Type::Category _category); bool isInteger(frontend::Type const& _type);
bool isFixedPoint(frontend::Type::Category _category); bool isFixedPoint(frontend::Type const& _type);
bool isRational(frontend::Type::Category _category); bool isRational(frontend::Type const& _type);
bool isFixedBytes(frontend::Type::Category _category); bool isFixedBytes(frontend::Type const& _type);
bool isAddress(frontend::Type::Category _category); bool isAddress(frontend::Type const& _type);
bool isContract(frontend::Type::Category _category); bool isContract(frontend::Type const& _type);
bool isEnum(frontend::Type::Category _category); bool isEnum(frontend::Type const& _type);
bool isNumber(frontend::Type::Category _category); bool isNumber(frontend::Type const& _type);
bool isBool(frontend::Type::Category _category); bool isBool(frontend::Type const& _type);
bool isFunction(frontend::Type::Category _category); bool isFunction(frontend::Type const& _type);
bool isMapping(frontend::Type::Category _category); bool isMapping(frontend::Type const& _type);
bool isArray(frontend::Type::Category _category); bool isArray(frontend::Type const& _type);
bool isTuple(frontend::Type::Category _category); bool isTuple(frontend::Type const& _type);
bool isStringLiteral(frontend::Type::Category _category); bool isStringLiteral(frontend::Type const& _type);
bool isStruct(frontend::Type::Category _category); bool isNonRecursiveStruct(frontend::Type const& _type);
/// Returns a new symbolic variable, according to _type. /// Returns a new symbolic variable, according to _type.
/// Also returns whether the type is abstract or not, /// Also returns whether the type is abstract or not,

View File

@ -121,7 +121,7 @@ SymbolicIntVariable::SymbolicIntVariable(
): ):
SymbolicVariable(_type, _originalType, move(_uniqueName), _context) SymbolicVariable(_type, _originalType, move(_uniqueName), _context)
{ {
solAssert(isNumber(m_type->category()), ""); solAssert(isNumber(*m_type), "");
} }
SymbolicAddressVariable::SymbolicAddressVariable( SymbolicAddressVariable::SymbolicAddressVariable(
@ -221,7 +221,7 @@ SymbolicEnumVariable::SymbolicEnumVariable(
): ):
SymbolicVariable(_type, _type, move(_uniqueName), _context) SymbolicVariable(_type, _type, move(_uniqueName), _context)
{ {
solAssert(isEnum(m_type->category()), ""); solAssert(isEnum(*m_type), "");
} }
SymbolicTupleVariable::SymbolicTupleVariable( SymbolicTupleVariable::SymbolicTupleVariable(
@ -231,7 +231,7 @@ SymbolicTupleVariable::SymbolicTupleVariable(
): ):
SymbolicVariable(_type, _type, move(_uniqueName), _context) SymbolicVariable(_type, _type, move(_uniqueName), _context)
{ {
solAssert(isTuple(m_type->category()), ""); solAssert(isTuple(*m_type), "");
} }
SymbolicTupleVariable::SymbolicTupleVariable( SymbolicTupleVariable::SymbolicTupleVariable(
@ -277,7 +277,7 @@ SymbolicArrayVariable::SymbolicArrayVariable(
m_context m_context
) )
{ {
solAssert(isArray(m_type->category()) || isMapping(m_type->category()), ""); solAssert(isArray(*m_type) || isMapping(*m_type), "");
} }
SymbolicArrayVariable::SymbolicArrayVariable( SymbolicArrayVariable::SymbolicArrayVariable(
@ -330,7 +330,7 @@ SymbolicStructVariable::SymbolicStructVariable(
): ):
SymbolicVariable(_type, _type, move(_uniqueName), _context) SymbolicVariable(_type, _type, move(_uniqueName), _context)
{ {
solAssert(isStruct(m_type->category()), ""); solAssert(isNonRecursiveStruct(*m_type), "");
auto const* structType = dynamic_cast<StructType const*>(_type); auto const* structType = dynamic_cast<StructType const*>(_type);
solAssert(structType, ""); solAssert(structType, "");
auto const& members = structType->structDefinition().members(); auto const& members = structType->structDefinition().members();