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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReferencesResolver::endVisit(NewExpression const& _new)
|
||||||
|
{
|
||||||
|
typeFor(_new.typeName());
|
||||||
|
}
|
||||||
|
|
||||||
bool ReferencesResolver::visit(UserDefinedTypeName const& _typeName)
|
bool ReferencesResolver::visit(UserDefinedTypeName const& _typeName)
|
||||||
{
|
{
|
||||||
Declaration const* declaration = m_resolver.pathFromCurrentScope(_typeName.namePath());
|
Declaration const* declaration = m_resolver.pathFromCurrentScope(_typeName.namePath());
|
||||||
|
@ -64,6 +64,7 @@ private:
|
|||||||
virtual bool visit(Identifier const& _identifier) override;
|
virtual bool visit(Identifier const& _identifier) override;
|
||||||
virtual bool visit(UserDefinedTypeName const& _typeName) override;
|
virtual bool visit(UserDefinedTypeName const& _typeName) override;
|
||||||
virtual bool visit(Return const& _return) override;
|
virtual bool visit(Return const& _return) override;
|
||||||
|
virtual void endVisit(NewExpression const& _new) override;
|
||||||
virtual void endVisit(VariableDeclaration const& _variable) override;
|
virtual void endVisit(VariableDeclaration const& _variable) override;
|
||||||
|
|
||||||
TypePointer typeFor(TypeName const& _typeName);
|
TypePointer typeFor(TypeName const& _typeName);
|
||||||
|
@ -1045,6 +1045,9 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
|||||||
|
|
||||||
void TypeChecker::endVisit(NewExpression const& _newExpression)
|
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()))
|
if (auto contractName = dynamic_cast<UserDefinedTypeName const*>(&_newExpression.typeName()))
|
||||||
{
|
{
|
||||||
auto contract = dynamic_cast<ContractDefinition const*>(&dereference(*contractName));
|
auto contract = dynamic_cast<ContractDefinition const*>(&dereference(*contractName));
|
||||||
@ -1076,9 +1079,26 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
|
|||||||
FunctionType::Location::Creation
|
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
|
else
|
||||||
fatalTypeError(_newExpression.location(), "Contract or array type expected.");
|
fatalTypeError(_newExpression.location(), "Contract or array type expected.");
|
||||||
|
@ -141,9 +141,6 @@ public:
|
|||||||
/// Factory functions that convert an AST @ref TypeName to a Type.
|
/// Factory functions that convert an AST @ref TypeName to a Type.
|
||||||
static TypePointer fromElementaryTypeName(Token::Value _typeToken);
|
static TypePointer fromElementaryTypeName(Token::Value _typeToken);
|
||||||
static TypePointer fromElementaryTypeName(std::string const& _name);
|
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
|
/// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
|
||||||
@ -751,7 +748,8 @@ public:
|
|||||||
AddMod, ///< ADDMOD
|
AddMod, ///< ADDMOD
|
||||||
MulMod, ///< MULMOD
|
MulMod, ///< MULMOD
|
||||||
ArrayPush, ///< .push() to a dynamically sized array in storage
|
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; }
|
virtual Category category() const override { return Category::Function; }
|
||||||
|
@ -2538,7 +2538,7 @@ BOOST_AUTO_TEST_CASE(create_memory_arrays)
|
|||||||
}
|
}
|
||||||
contract C {
|
contract C {
|
||||||
function f(uint size) {
|
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 y = new uint[](20);
|
||||||
var z = new bytes(size);
|
var z = new bytes(size);
|
||||||
}
|
}
|
||||||
@ -2547,6 +2547,42 @@ BOOST_AUTO_TEST_CASE(create_memory_arrays)
|
|||||||
BOOST_CHECK(success(text));
|
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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user