aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-11-17 08:47:47 +0800
committerchriseth <c@ethdev.com>2015-11-26 20:10:12 +0800
commitbf55aa6ae2b9aeec09bb8cf1e3715afd7dd59b7e (patch)
treee49bc5845496df706ea45de03748c5475611c3b9
parent30b325fdc148d5014f04fd238362e3a1df10310f (diff)
downloaddexon-solidity-bf55aa6ae2b9aeec09bb8cf1e3715afd7dd59b7e.tar.gz
dexon-solidity-bf55aa6ae2b9aeec09bb8cf1e3715afd7dd59b7e.tar.zst
dexon-solidity-bf55aa6ae2b9aeec09bb8cf1e3715afd7dd59b7e.zip
Type checking for creating new arrays.
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp5
-rw-r--r--libsolidity/analysis/ReferencesResolver.h1
-rw-r--r--libsolidity/analysis/TypeChecker.cpp24
-rw-r--r--libsolidity/ast/Types.h6
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp38
5 files changed, 67 insertions, 7 deletions
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index 0e153045..408212f1 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -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());
diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h
index 21cb1d35..62104611 100644
--- a/libsolidity/analysis/ReferencesResolver.h
+++ b/libsolidity/analysis/ReferencesResolver.h
@@ -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);
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 13c2235a..5623da37 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -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.");
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index f5aefa25..63207a51 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -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; }
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 3d9dc5b5..4f26fa4d 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -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()
}