diff options
author | chriseth <c@ethdev.com> | 2015-11-26 22:28:28 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-11-26 22:28:28 +0800 |
commit | c498dcce22b2921ee57f280da9117e491c021e1b (patch) | |
tree | 1eb3bec6140d9b2e1ee57f62343dbc9c70d84c78 /libsolidity/analysis | |
parent | cd94aa978a77ace1296f9978bfae6d8735b5c91d (diff) | |
parent | e06768e8b580d009b9a9905f70ae2d8814699115 (diff) | |
download | dexon-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.cpp | 6 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.cpp | 9 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.h | 1 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 87 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.h | 4 |
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. |