mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10605 from ethereum/develop
Merge develop into breaking.
This commit is contained in:
@@ -1895,9 +1895,13 @@ std::unique_ptr<ReferenceType> ArrayType::copyForLocation(DataLocation _location
|
||||
|
||||
BoolResult ArraySliceType::isImplicitlyConvertibleTo(Type const& _other) const
|
||||
{
|
||||
if (m_arrayType.location() == DataLocation::CallData && m_arrayType.isDynamicallySized() && m_arrayType == _other)
|
||||
return true;
|
||||
return (*this) == _other;
|
||||
return
|
||||
(*this) == _other ||
|
||||
(
|
||||
m_arrayType.dataStoredIn(DataLocation::CallData) &&
|
||||
m_arrayType.isDynamicallySized() &&
|
||||
m_arrayType.isImplicitlyConvertibleTo(_other)
|
||||
);
|
||||
}
|
||||
|
||||
string ArraySliceType::richIdentifier() const
|
||||
|
||||
@@ -1050,18 +1050,18 @@ void CompilerUtils::convertType(
|
||||
}
|
||||
case Type::Category::ArraySlice:
|
||||
{
|
||||
solAssert(_targetType.category() == Type::Category::Array, "");
|
||||
auto& typeOnStack = dynamic_cast<ArraySliceType const&>(_typeOnStack);
|
||||
solUnimplementedAssert(
|
||||
_targetType.dataStoredIn(DataLocation::CallData),
|
||||
"Conversion from calldata slices to memory not yet implemented."
|
||||
);
|
||||
solAssert(_targetType == typeOnStack.arrayType(), "");
|
||||
solUnimplementedAssert(
|
||||
typeOnStack.arrayType().location() == DataLocation::CallData &&
|
||||
auto const& targetArrayType = dynamic_cast<ArrayType const&>(_targetType);
|
||||
solAssert(typeOnStack.arrayType().isImplicitlyConvertibleTo(targetArrayType), "");
|
||||
solAssert(
|
||||
typeOnStack.arrayType().dataStoredIn(DataLocation::CallData) &&
|
||||
typeOnStack.arrayType().isDynamicallySized() &&
|
||||
!typeOnStack.arrayType().baseType()->isDynamicallyEncoded(),
|
||||
""
|
||||
);
|
||||
if (!_targetType.dataStoredIn(DataLocation::CallData))
|
||||
return convertType(typeOnStack.arrayType(), _targetType);
|
||||
break;
|
||||
}
|
||||
case Type::Category::Struct:
|
||||
|
||||
@@ -2946,19 +2946,21 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
|
||||
}
|
||||
else if (_from.category() == Type::Category::ArraySlice)
|
||||
{
|
||||
solAssert(_from.isDynamicallySized(), "");
|
||||
solAssert(_from.dataStoredIn(DataLocation::CallData), "");
|
||||
solAssert(_to.category() == Type::Category::Array, "");
|
||||
auto const& fromType = dynamic_cast<ArraySliceType const&>(_from);
|
||||
auto const& targetType = dynamic_cast<ArrayType const&>(_to);
|
||||
|
||||
ArraySliceType const& fromType = dynamic_cast<ArraySliceType const&>(_from);
|
||||
ArrayType const& targetType = dynamic_cast<ArrayType const&>(_to);
|
||||
|
||||
solAssert(!fromType.arrayType().baseType()->isDynamicallyEncoded(), "");
|
||||
solAssert(fromType.arrayType().isImplicitlyConvertibleTo(targetType), "");
|
||||
solAssert(
|
||||
*fromType.arrayType().baseType() == *targetType.baseType(),
|
||||
"Converting arrays of different type is not possible"
|
||||
fromType.arrayType().dataStoredIn(DataLocation::CallData) &&
|
||||
fromType.arrayType().isDynamicallySized() &&
|
||||
!fromType.arrayType().baseType()->isDynamicallyEncoded(),
|
||||
""
|
||||
);
|
||||
|
||||
if (!targetType.dataStoredIn(DataLocation::CallData))
|
||||
return arrayConversionFunction(fromType.arrayType(), targetType);
|
||||
|
||||
string const functionName =
|
||||
"convert_" +
|
||||
_from.identifier() +
|
||||
|
||||
@@ -507,18 +507,21 @@ void SMTEncoder::endVisit(UnaryOperation const& _op)
|
||||
{
|
||||
solAssert(smt::isInteger(*type) || smt::isFixedPoint(*type), "");
|
||||
solAssert(subExpr->annotation().willBeWrittenTo, "");
|
||||
auto computeNewValue = [&](auto currentValue) {
|
||||
return arithmeticOperation(
|
||||
_op.getOperator() == Token::Inc ? Token::Add : Token::Sub,
|
||||
currentValue,
|
||||
smtutil::Expression(size_t(1)),
|
||||
_op.annotation().type,
|
||||
_op
|
||||
).first;
|
||||
};
|
||||
if (auto identifier = dynamic_cast<Identifier const*>(subExpr))
|
||||
{
|
||||
auto decl = identifierToVariable(*identifier);
|
||||
solAssert(decl, "");
|
||||
auto innerValue = currentValue(*decl);
|
||||
auto newValue = arithmeticOperation(
|
||||
_op.getOperator() == Token::Inc ? Token::Add : Token::Sub,
|
||||
innerValue,
|
||||
smtutil::Expression(size_t(1)),
|
||||
_op.annotation().type,
|
||||
_op
|
||||
).first;
|
||||
auto newValue = computeNewValue(innerValue);
|
||||
defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue);
|
||||
assignment(*decl, newValue);
|
||||
}
|
||||
@@ -528,16 +531,17 @@ void SMTEncoder::endVisit(UnaryOperation const& _op)
|
||||
)
|
||||
{
|
||||
auto innerValue = expr(*subExpr);
|
||||
auto newValue = arithmeticOperation(
|
||||
_op.getOperator() == Token::Inc ? Token::Add : Token::Sub,
|
||||
innerValue,
|
||||
smtutil::Expression(size_t(1)),
|
||||
_op.annotation().type,
|
||||
_op
|
||||
).first;
|
||||
auto newValue = computeNewValue(innerValue);
|
||||
defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue);
|
||||
indexOrMemberAssignment(*subExpr, newValue);
|
||||
}
|
||||
else if (isEmptyPush(*subExpr))
|
||||
{
|
||||
auto innerValue = expr(*subExpr);
|
||||
auto newValue = computeNewValue(innerValue);
|
||||
defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue);
|
||||
arrayPushPopAssign(*subExpr, newValue);
|
||||
}
|
||||
else
|
||||
solAssert(false, "");
|
||||
|
||||
@@ -709,6 +713,7 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall)
|
||||
break;
|
||||
}
|
||||
case FunctionType::Kind::ArrayPush:
|
||||
case FunctionType::Kind::ByteArrayPush:
|
||||
arrayPush(_funCall);
|
||||
break;
|
||||
case FunctionType::Kind::ArrayPop:
|
||||
@@ -1134,8 +1139,12 @@ 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); }));
|
||||
if (smt::isNonRecursiveStruct(*_funCall.annotation().type))
|
||||
{
|
||||
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)
|
||||
@@ -1567,6 +1576,8 @@ void SMTEncoder::arrayPushPopAssign(Expression const& _expr, smtutil::Expression
|
||||
else if (auto const* funCall = dynamic_cast<FunctionCall const*>(expr))
|
||||
{
|
||||
FunctionType const& funType = dynamic_cast<FunctionType const&>(*funCall->expression().annotation().type);
|
||||
// Push cannot occur on an expression that is itself a ByteArrayPush, i.e., bytes.push().push() is not possible.
|
||||
solAssert(funType.kind() != FunctionType::Kind::ByteArrayPush, "");
|
||||
if (funType.kind() == FunctionType::Kind::ArrayPush)
|
||||
{
|
||||
auto memberAccess = dynamic_cast<MemberAccess const*>(&funCall->expression());
|
||||
@@ -2494,7 +2505,7 @@ MemberAccess const* SMTEncoder::isEmptyPush(Expression const& _expr) const
|
||||
)
|
||||
{
|
||||
auto const& funType = dynamic_cast<FunctionType const&>(*funCall->expression().annotation().type);
|
||||
if (funType.kind() == FunctionType::Kind::ArrayPush)
|
||||
if (funType.kind() == FunctionType::Kind::ArrayPush || funType.kind() == FunctionType::Kind::ByteArrayPush)
|
||||
return &dynamic_cast<MemberAccess const&>(funCall->expression());
|
||||
}
|
||||
return nullptr;
|
||||
@@ -2542,10 +2553,10 @@ FunctionDefinition const* SMTEncoder::functionCallToDefinition(FunctionCall cons
|
||||
FunctionDefinition const* funDef = nullptr;
|
||||
Expression const* calledExpr = &_funCall.expression();
|
||||
|
||||
if (TupleExpression const* fun = dynamic_cast<TupleExpression const*>(&_funCall.expression()))
|
||||
if (TupleExpression const* fun = dynamic_cast<TupleExpression const*>(calledExpr))
|
||||
{
|
||||
solAssert(fun->components().size() == 1, "");
|
||||
calledExpr = fun->components().front().get();
|
||||
calledExpr = innermostTuple(*calledExpr);
|
||||
}
|
||||
|
||||
if (Identifier const* fun = dynamic_cast<Identifier const*>(calledExpr))
|
||||
@@ -2596,8 +2607,11 @@ vector<VariableDeclaration const*> SMTEncoder::modifiersVariables(FunctionDefini
|
||||
continue;
|
||||
|
||||
visited.insert(modifier);
|
||||
vars += applyMap(modifier->parameters(), [](auto _var) { return _var.get(); });
|
||||
vars += BlockVars(modifier->body()).vars;
|
||||
if (modifier->isImplemented())
|
||||
{
|
||||
vars += applyMap(modifier->parameters(), [](auto _var) { return _var.get(); });
|
||||
vars += BlockVars(modifier->body()).vars;
|
||||
}
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
@@ -2684,6 +2698,7 @@ vector<smtutil::Expression> SMTEncoder::symbolicArguments(FunctionCall const& _f
|
||||
unsigned firstParam = 0;
|
||||
if (funType->bound())
|
||||
{
|
||||
calledExpr = innermostTuple(*calledExpr);
|
||||
auto const& boundFunction = dynamic_cast<MemberAccess const*>(calledExpr);
|
||||
solAssert(boundFunction, "");
|
||||
args.push_back(expr(boundFunction->expression(), functionParams.front()->type()));
|
||||
|
||||
Reference in New Issue
Block a user