mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Type checking for creating new arrays.
This commit is contained in:
parent
30b325fdc1
commit
bf55aa6ae2
@ -37,6 +37,11 @@ bool ReferencesResolver::visit(Return const& _return)
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReferencesResolver::endVisit(NewExpression const& _new)
|
||||
{
|
||||
typeFor(_new.typeName());
|
||||
}
|
||||
|
||||
bool ReferencesResolver::visit(UserDefinedTypeName const& _typeName)
|
||||
{
|
||||
Declaration const* declaration = m_resolver.pathFromCurrentScope(_typeName.namePath());
|
||||
|
@ -64,6 +64,7 @@ private:
|
||||
virtual bool visit(Identifier const& _identifier) override;
|
||||
virtual bool visit(UserDefinedTypeName const& _typeName) override;
|
||||
virtual bool visit(Return const& _return) override;
|
||||
virtual void endVisit(NewExpression const& _new) override;
|
||||
virtual void endVisit(VariableDeclaration const& _variable) override;
|
||||
|
||||
TypePointer typeFor(TypeName const& _typeName);
|
||||
|
@ -1045,6 +1045,9 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
|
||||
void TypeChecker::endVisit(NewExpression const& _newExpression)
|
||||
{
|
||||
TypePointer type = _newExpression.typeName().annotation().type;
|
||||
solAssert(!!type, "Type name not resolved.");
|
||||
|
||||
if (auto contractName = dynamic_cast<UserDefinedTypeName const*>(&_newExpression.typeName()))
|
||||
{
|
||||
auto contract = dynamic_cast<ContractDefinition const*>(&dereference(*contractName));
|
||||
@ -1076,9 +1079,26 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
|
||||
FunctionType::Location::Creation
|
||||
);
|
||||
}
|
||||
else if (auto arrayTypeName = dynamic_cast<ArrayTypeName const*>(&_newExpression.typeName()))
|
||||
else if (type->category() == Type::Category::Array)
|
||||
{
|
||||
solAssert(false, "Not yet implemented.");
|
||||
if (!type->canLiveOutsideStorage())
|
||||
fatalTypeError(
|
||||
_newExpression.typeName().location(),
|
||||
"Type cannot live outside storage."
|
||||
);
|
||||
if (!type->isDynamicallySized())
|
||||
typeError(
|
||||
_newExpression.typeName().location(),
|
||||
"Length has to be placed in parentheses after the array type for new expression."
|
||||
);
|
||||
type = ReferenceType::copyForLocationIfReference(DataLocation::Memory, type);
|
||||
_newExpression.annotation().type = make_shared<FunctionType>(
|
||||
TypePointers{make_shared<IntegerType>(256)},
|
||||
TypePointers{type},
|
||||
strings(),
|
||||
strings(),
|
||||
FunctionType::Location::ObjectCreation
|
||||
);
|
||||
}
|
||||
else
|
||||
fatalTypeError(_newExpression.location(), "Contract or array type expected.");
|
||||
|
@ -141,9 +141,6 @@ public:
|
||||
/// Factory functions that convert an AST @ref TypeName to a Type.
|
||||
static TypePointer fromElementaryTypeName(Token::Value _typeToken);
|
||||
static TypePointer fromElementaryTypeName(std::string const& _name);
|
||||
static TypePointer fromUserDefinedTypeName(UserDefinedTypeName const& _typeName);
|
||||
static TypePointer fromMapping(ElementaryTypeName& _keyType, TypeName& _valueType);
|
||||
static TypePointer fromArrayTypeName(TypeName& _baseTypeName, Expression* _length);
|
||||
/// @}
|
||||
|
||||
/// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
|
||||
@ -751,7 +748,8 @@ public:
|
||||
AddMod, ///< ADDMOD
|
||||
MulMod, ///< MULMOD
|
||||
ArrayPush, ///< .push() to a dynamically sized array in storage
|
||||
ByteArrayPush ///< .push() to a dynamically sized byte array in storage
|
||||
ByteArrayPush, ///< .push() to a dynamically sized byte array in storage
|
||||
ObjectCreation ///< array creation using new
|
||||
};
|
||||
|
||||
virtual Category category() const override { return Category::Function; }
|
||||
|
@ -2538,7 +2538,7 @@ BOOST_AUTO_TEST_CASE(create_memory_arrays)
|
||||
}
|
||||
contract C {
|
||||
function f(uint size) {
|
||||
L.S[][] x = new L.S[][](10);
|
||||
L.S[][] memory x = new L.S[][](10);
|
||||
var y = new uint[](20);
|
||||
var z = new bytes(size);
|
||||
}
|
||||
@ -2547,6 +2547,42 @@ BOOST_AUTO_TEST_CASE(create_memory_arrays)
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(mapping_in_memory_array)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
function f(uint size) {
|
||||
var x = new mapping(uint => uint)[](4);
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(new_for_non_array)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
function f(uint size) {
|
||||
var x = new uint(7);
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
function f(uint size) {
|
||||
var x = new uint[]();
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user