From 09b2f9acb7f5f47f53c4b56fdf0f86946551bf12 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 26 Nov 2015 11:37:29 +0100 Subject: Resolve type names using regular AST visit. --- libsolidity/analysis/ReferencesResolver.cpp | 140 ++++++++++++---------------- libsolidity/analysis/ReferencesResolver.h | 8 +- 2 files changed, 66 insertions(+), 82 deletions(-) (limited to 'libsolidity/analysis') diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index e5b1c52b..17f93029 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -31,28 +31,6 @@ using namespace dev; using namespace dev::solidity; -bool ReferencesResolver::visit(Return const& _return) -{ - _return.annotation().functionReturnParameters = m_returnParameters; - 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()); - if (!declaration) - fatalDeclarationError(_typeName.location(), "Identifier not found or not unique."); - - _typeName.annotation().referencedDeclaration = declaration; - - return true; -} - bool ReferencesResolver::resolve(ASTNode const& _root) { try @@ -79,6 +57,67 @@ bool ReferencesResolver::visit(Identifier const& _identifier) return false; } +bool ReferencesResolver::visit(ElementaryTypeName const& _typeName) +{ + _typeName.annotation().type = Type::fromElementaryTypeName(_typeName.typeName()); + return true; +} + +void ReferencesResolver::endVisit(UserDefinedTypeName const& _typeName) +{ + Declaration const* declaration = m_resolver.pathFromCurrentScope(_typeName.namePath()); + if (!declaration) + fatalDeclarationError(_typeName.location(), "Identifier not found or not unique."); + + _typeName.annotation().referencedDeclaration = declaration; + + if (StructDefinition const* structDef = dynamic_cast(declaration)) + _typeName.annotation().type = make_shared(*structDef); + else if (EnumDefinition const* enumDef = dynamic_cast(declaration)) + _typeName.annotation().type = make_shared(*enumDef); + else if (ContractDefinition const* contract = dynamic_cast(declaration)) + _typeName.annotation().type = make_shared(*contract); + else + fatalTypeError(_typeName.location(), "Name has to refer to a struct, enum or contract."); +} + +void ReferencesResolver::endVisit(Mapping const& _typeName) +{ + TypePointer keyType = _typeName.keyType().annotation().type; + TypePointer valueType = _typeName.valueType().annotation().type; + // Convert key type to memory. + keyType = ReferenceType::copyForLocationIfReference(DataLocation::Memory, keyType); + // Convert value type to storage reference. + valueType = ReferenceType::copyForLocationIfReference(DataLocation::Storage, valueType); + _typeName.annotation().type = make_shared(keyType, valueType); +} + +void ReferencesResolver::endVisit(ArrayTypeName const& _typeName) +{ + TypePointer baseType = _typeName.baseType().annotation().type; + if (baseType->storageBytes() == 0) + fatalTypeError(_typeName.baseType().location(), "Illegal base type of storage size zero for array."); + if (Expression const* length = _typeName.length()) + { + if (!length->annotation().type) + ConstantEvaluator e(*length); + + auto const* lengthType = dynamic_cast(length->annotation().type.get()); + if (!lengthType) + fatalTypeError(length->location(), "Invalid array length."); + else + _typeName.annotation().type = make_shared(DataLocation::Storage, baseType, lengthType->literalValue(nullptr)); + } + else + _typeName.annotation().type = make_shared(DataLocation::Storage, baseType); +} + +bool ReferencesResolver::visit(Return const& _return) +{ + _return.annotation().functionReturnParameters = m_returnParameters; + return true; +} + void ReferencesResolver::endVisit(VariableDeclaration const& _variable) { if (_variable.annotation().type) @@ -87,7 +126,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) TypePointer type; if (_variable.typeName()) { - type = typeFor(*_variable.typeName()); + type = _variable.typeName()->annotation().type; using Location = VariableDeclaration::Location; Location loc = _variable.referenceLocation(); // References are forced to calldata for external function parameters (not return) @@ -167,61 +206,6 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) _variable.annotation().type = type; } -TypePointer ReferencesResolver::typeFor(TypeName const& _typeName) -{ - if (_typeName.annotation().type) - return _typeName.annotation().type; - - TypePointer type; - if (auto elemTypeName = dynamic_cast(&_typeName)) - type = Type::fromElementaryTypeName(elemTypeName->typeName()); - else if (auto typeName = dynamic_cast(&_typeName)) - { - Declaration const* declaration = typeName->annotation().referencedDeclaration; - solAssert(!!declaration, ""); - - if (StructDefinition const* structDef = dynamic_cast(declaration)) - type = make_shared(*structDef); - else if (EnumDefinition const* enumDef = dynamic_cast(declaration)) - type = make_shared(*enumDef); - else if (ContractDefinition const* contract = dynamic_cast(declaration)) - type = make_shared(*contract); - else - fatalTypeError(typeName->location(), "Name has to refer to a struct, enum or contract."); - } - else if (auto mapping = dynamic_cast(&_typeName)) - { - TypePointer keyType = typeFor(mapping->keyType()); - TypePointer valueType = typeFor(mapping->valueType()); - // Convert key type to memory. - keyType = ReferenceType::copyForLocationIfReference(DataLocation::Memory, keyType); - // Convert value type to storage reference. - valueType = ReferenceType::copyForLocationIfReference(DataLocation::Storage, valueType); - type = make_shared(keyType, valueType); - } - else if (auto arrayType = dynamic_cast(&_typeName)) - { - TypePointer baseType = typeFor(arrayType->baseType()); - if (baseType->storageBytes() == 0) - fatalTypeError(arrayType->baseType().location(), "Illegal base type of storage size zero for array."); - if (Expression const* length = arrayType->length()) - { - if (!length->annotation().type) - ConstantEvaluator e(*length); - - auto const* lengthType = dynamic_cast(length->annotation().type.get()); - if (!lengthType) - fatalTypeError(length->location(), "Invalid array length."); - else - type = make_shared(DataLocation::Storage, baseType, lengthType->literalValue(nullptr)); - } - else - type = make_shared(DataLocation::Storage, baseType); - } - - return _typeName.annotation().type = move(type); -} - void ReferencesResolver::typeError(SourceLocation const& _location, string const& _description) { auto err = make_shared(Error::Type::TypeError); diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 6f5ced8c..a2d71dc3 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -60,13 +60,13 @@ public: private: virtual bool visit(Block const&) override { return m_resolveInsideCode; } virtual bool visit(Identifier const& _identifier) override; - virtual bool visit(UserDefinedTypeName const& _typeName) override; + virtual bool visit(ElementaryTypeName const& _typeName) override; + virtual void endVisit(UserDefinedTypeName const& _typeName) override; + virtual void endVisit(Mapping const& _typeName) override; + virtual void endVisit(ArrayTypeName 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); - /// Adds a new error to the list of errors. void typeError(SourceLocation const& _location, std::string const& _description); -- cgit