aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/analysis
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-11-26 22:28:28 +0800
committerchriseth <c@ethdev.com>2015-11-26 22:28:28 +0800
commitc498dcce22b2921ee57f280da9117e491c021e1b (patch)
tree1eb3bec6140d9b2e1ee57f62343dbc9c70d84c78 /libsolidity/analysis
parentcd94aa978a77ace1296f9978bfae6d8735b5c91d (diff)
parente06768e8b580d009b9a9905f70ae2d8814699115 (diff)
downloaddexon-solidity-c498dcce22b2921ee57f280da9117e491c021e1b.tar
dexon-solidity-c498dcce22b2921ee57f280da9117e491c021e1b.tar.gz
dexon-solidity-c498dcce22b2921ee57f280da9117e491c021e1b.tar.bz2
dexon-solidity-c498dcce22b2921ee57f280da9117e491c021e1b.tar.lz
dexon-solidity-c498dcce22b2921ee57f280da9117e491c021e1b.tar.xz
dexon-solidity-c498dcce22b2921ee57f280da9117e491c021e1b.tar.zst
dexon-solidity-c498dcce22b2921ee57f280da9117e491c021e1b.zip
Merge pull request #222 from chriseth/newArrays
Dynamically create memory arrays.
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp6
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp9
-rw-r--r--libsolidity/analysis/ReferencesResolver.h1
-rw-r--r--libsolidity/analysis/TypeChecker.cpp87
-rw-r--r--libsolidity/analysis/TypeChecker.h4
5 files changed, 76 insertions, 31 deletions
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp
index 806f1322..fa894456 100644
--- a/libsolidity/analysis/NameAndTypeResolver.cpp
+++ b/libsolidity/analysis/NameAndTypeResolver.cpp
@@ -49,7 +49,7 @@ bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit)
{
DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errors);
}
- catch (FatalError const& _e)
+ catch (FatalError const&)
{
if (m_errors.empty())
throw; // Something is weird here, rather throw again.
@@ -146,7 +146,7 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
if (!success)
return false;
}
- catch (FatalError const& _e)
+ catch (FatalError const&)
{
if (m_errors.empty())
throw; // Something is weird here, rather throw again.
@@ -162,7 +162,7 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration)
m_scopes[nullptr].registerDeclaration(_declaration, false, true);
solAssert(_declaration.scope() == nullptr, "Updated declaration outside global scope.");
}
- catch (FatalError const& _error)
+ catch (FatalError const&)
{
if (m_errors.empty())
throw; // Something is weird here, rather throw again.
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index 95643578..f0afc4f9 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());
@@ -44,6 +49,8 @@ bool ReferencesResolver::visit(UserDefinedTypeName const& _typeName)
fatalDeclarationError(_typeName.location(), "Identifier not found or not unique.");
_typeName.annotation().referencedDeclaration = declaration;
+
+ _typeName.annotation().contractScope = m_currentContract;
return true;
}
@@ -53,7 +60,7 @@ bool ReferencesResolver::resolve(ASTNode& _root)
{
_root.accept(*this);
}
- catch (FatalError const& e)
+ catch (FatalError const&)
{
solAssert(m_errorOccurred, "");
}
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 0990a9e4..42fdad91 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -1045,34 +1045,63 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
void TypeChecker::endVisit(NewExpression const& _newExpression)
{
- auto contract = dynamic_cast<ContractDefinition const*>(&dereference(_newExpression.contractName()));
+ TypePointer type = _newExpression.typeName().annotation().type;
+ solAssert(!!type, "Type name not resolved.");
- if (!contract)
- fatalTypeError(_newExpression.location(), "Identifier is not a contract.");
- if (!contract->annotation().isFullyImplemented)
- typeError(_newExpression.location(), "Trying to create an instance of an abstract contract.");
-
- auto scopeContract = _newExpression.contractName().annotation().contractScope;
- scopeContract->annotation().contractDependencies.insert(contract);
- solAssert(
- !contract->annotation().linearizedBaseContracts.empty(),
- "Linearized base contracts not yet available."
- );
- if (contractDependenciesAreCyclic(*scopeContract))
- typeError(
- _newExpression.location(),
- "Circular reference for contract creation (cannot create instance of derived or same contract)."
+ if (auto contractName = dynamic_cast<UserDefinedTypeName const*>(&_newExpression.typeName()))
+ {
+ auto contract = dynamic_cast<ContractDefinition const*>(&dereference(*contractName));
+
+ if (!contract)
+ fatalTypeError(_newExpression.location(), "Identifier is not a contract.");
+ if (!contract->annotation().isFullyImplemented)
+ typeError(_newExpression.location(), "Trying to create an instance of an abstract contract.");
+
+ auto scopeContract = contractName->annotation().contractScope;
+ scopeContract->annotation().contractDependencies.insert(contract);
+ solAssert(
+ !contract->annotation().linearizedBaseContracts.empty(),
+ "Linearized base contracts not yet available."
);
+ if (contractDependenciesAreCyclic(*scopeContract))
+ typeError(
+ _newExpression.location(),
+ "Circular reference for contract creation (cannot create instance of derived or same contract)."
+ );
- auto contractType = make_shared<ContractType>(*contract);
- TypePointers const& parameterTypes = contractType->constructorType()->parameterTypes();
- _newExpression.annotation().type = make_shared<FunctionType>(
- parameterTypes,
- TypePointers{contractType},
- strings(),
- strings(),
- FunctionType::Location::Creation
- );
+ auto contractType = make_shared<ContractType>(*contract);
+ TypePointers const& parameterTypes = contractType->constructorType()->parameterTypes();
+ _newExpression.annotation().type = make_shared<FunctionType>(
+ parameterTypes,
+ TypePointers{contractType},
+ strings(),
+ strings(),
+ FunctionType::Location::Creation
+ );
+ }
+ else if (type->category() == Type::Category::Array)
+ {
+ 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.");
}
bool TypeChecker::visit(MemberAccess const& _memberAccess)
@@ -1282,12 +1311,18 @@ bool TypeChecker::contractDependenciesAreCyclic(
return false;
}
-Declaration const& TypeChecker::dereference(Identifier const& _identifier)
+Declaration const& TypeChecker::dereference(Identifier const& _identifier) const
{
solAssert(!!_identifier.annotation().referencedDeclaration, "Declaration not stored.");
return *_identifier.annotation().referencedDeclaration;
}
+Declaration const& TypeChecker::dereference(UserDefinedTypeName const& _typeName) const
+{
+ solAssert(!!_typeName.annotation().referencedDeclaration, "Declaration not stored.");
+ return *_typeName.annotation().referencedDeclaration;
+}
+
void TypeChecker::expectType(Expression const& _expression, Type const& _expectedType)
{
_expression.accept(*this);
diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h
index f163f47c..2295bc22 100644
--- a/libsolidity/analysis/TypeChecker.h
+++ b/libsolidity/analysis/TypeChecker.h
@@ -107,7 +107,9 @@ private:
) const;
/// @returns the referenced declaration and throws on error.
- Declaration const& dereference(Identifier const& _identifier);
+ Declaration const& dereference(Identifier const& _identifier) const;
+ /// @returns the referenced declaration and throws on error.
+ Declaration const& dereference(UserDefinedTypeName const& _typeName) const;
/// Runs type checks on @a _expression to infer its type and then checks that it is implicitly
/// convertible to @a _expectedType.