More checks for missing mobile type.

This commit is contained in:
chriseth 2016-10-21 12:30:58 +02:00
parent 6b028701a0
commit f25aa0c68b
5 changed files with 46 additions and 12 deletions

View File

@ -12,7 +12,8 @@ Bugfixes:
* Commandline interface: Disallow unknown options in ``solc``.
* Name resolver: Allow inheritance of ``enum`` definitions.
* Type checker: Proper type checking for bound functions.
* Type checker: fix crash related to invalid fixed point constants
* Type checker: fixed crash related to invalid fixed point constants
* Type checker: fixed crash related to invalid literal numbers.
* Code generator: expect zero stack increase after ``super`` as an expression.
* Code Generator: fixed an internal compiler error for ``L.Foo`` for ``enum Foo`` defined in library ``L``.
* Inline assembly: support the ``address`` opcode.

View File

@ -880,6 +880,10 @@ bool TypeChecker::visit(Conditional const& _conditional)
TypePointer trueType = type(_conditional.trueExpression())->mobileType();
TypePointer falseType = type(_conditional.falseExpression())->mobileType();
if (!trueType)
fatalTypeError(_conditional.trueExpression().location(), "Invalid mobile type.");
if (!falseType)
fatalTypeError(_conditional.falseExpression().location(), "Invalid mobile type.");
TypePointer commonType = Type::commonType(trueType, falseType);
if (!commonType)
@ -986,10 +990,16 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
types.push_back(type(*components[i]));
if (_tuple.isInlineArray())
solAssert(!!types[i], "Inline array cannot have empty components");
if (i == 0 && _tuple.isInlineArray())
inlineArrayType = types[i]->mobileType();
else if (_tuple.isInlineArray() && inlineArrayType)
inlineArrayType = Type::commonType(inlineArrayType, types[i]->mobileType());
if (_tuple.isInlineArray())
{
if ((i == 0 || inlineArrayType) && !types[i]->mobileType())
fatalTypeError(components[i]->location(), "Invalid mobile type.");
if (i == 0)
inlineArrayType = types[i]->mobileType();
else if (inlineArrayType)
inlineArrayType = Type::commonType(inlineArrayType, types[i]->mobileType());
}
}
else
types.push_back(TypePointer());

View File

@ -198,7 +198,9 @@ TypePointer Type::forLiteral(Literal const& _literal)
TypePointer Type::commonType(TypePointer const& _a, TypePointer const& _b)
{
if (_b->isImplicitlyConvertibleTo(*_a))
if (!_a || !_b)
return TypePointer();
else if (_b->isImplicitlyConvertibleTo(*_a))
return _a;
else if (_a->isImplicitlyConvertibleTo(*_b))
return _b;
@ -1661,7 +1663,17 @@ TypePointer TupleType::mobileType() const
{
TypePointers mobiles;
for (auto const& c: components())
mobiles.push_back(c ? c->mobileType() : TypePointer());
{
if (c)
{
auto mt = c->mobileType();
if (!mt)
return TypePointer();
mobiles.push_back(mt);
}
else
mobiles.push_back(TypePointer());
}
return make_shared<TupleType>(mobiles);
}

View File

@ -368,8 +368,11 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
m_context << (u256(1) << (256 - targetBytesType.numBytes() * 8)) << Instruction::MUL;
}
else if (targetTypeCategory == Type::Category::Enum)
{
solAssert(_typeOnStack.mobileType(), "");
// just clean
convertType(_typeOnStack, *_typeOnStack.mobileType(), true);
}
else if (targetTypeCategory == Type::Category::FixedPoint)
{
solAssert(

View File

@ -56,8 +56,10 @@ void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration c
if (_varDecl.annotation().type->dataStoredIn(DataLocation::Storage))
{
// reference type, only convert value to mobile type and do final conversion in storeValue.
utils().convertType(*type, *type->mobileType());
type = type->mobileType();
auto mt = type->mobileType();
solAssert(mt, "");
utils().convertType(*type, *mt);
type = mt;
}
else
{
@ -1437,11 +1439,17 @@ void ExpressionCompiler::appendExternalFunctionCall(
// Evaluate arguments.
TypePointers argumentTypes;
TypePointers parameterTypes = _functionType.parameterTypes();
bool manualFunctionId =
bool manualFunctionId = false;
if (
(funKind == FunctionKind::Bare || funKind == FunctionKind::BareCallCode || funKind == FunctionKind::BareDelegateCall) &&
!_arguments.empty() &&
_arguments.front()->annotation().type->mobileType()->calldataEncodedSize(false) ==
!_arguments.empty()
)
{
solAssert(_arguments.front()->annotation().type->mobileType(), "");
manualFunctionId =
_arguments.front()->annotation().type->mobileType()->calldataEncodedSize(false) ==
CompilerUtils::dataStartOffset;
}
if (manualFunctionId)
{
// If we have a Bare* and the first type has exactly 4 bytes, use it as