diff options
author | chriseth <c@ethdev.com> | 2015-11-30 23:06:44 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-11-30 23:06:44 +0800 |
commit | e9c7837c154482a72c8519fbdc9376693ce9a1d5 (patch) | |
tree | 1985b57b4e221fe4e4b5cc14a5049b8c0c46ce6c /libsolidity/analysis | |
parent | a8736b7b271dac117f15164cf4d2dfabcdd2c6fd (diff) | |
parent | f9e52c9db1ef23000f5721a462aba3fa8d681749 (diff) | |
download | dexon-solidity-e9c7837c154482a72c8519fbdc9376693ce9a1d5.tar.gz dexon-solidity-e9c7837c154482a72c8519fbdc9376693ce9a1d5.tar.zst dexon-solidity-e9c7837c154482a72c8519fbdc9376693ce9a1d5.zip |
Merge pull request #251 from chriseth/bind2
Bind library functions to types.
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r-- | libsolidity/analysis/NameAndTypeResolver.h | 4 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.cpp | 140 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.h | 8 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 22 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.h | 1 |
5 files changed, 89 insertions, 86 deletions
diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index 0d9b2477..1547a274 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -160,8 +160,8 @@ private: void fatalDeclarationError(SourceLocation _sourceLocation, std::string const& _description); std::map<ASTNode const*, DeclarationContainer>& m_scopes; - Declaration const* m_currentScope; - VariableScope* m_currentFunction; + Declaration const* m_currentScope = nullptr; + VariableScope* m_currentFunction = nullptr; ErrorList& m_errors; }; 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<StructDefinition const*>(declaration)) + _typeName.annotation().type = make_shared<StructType>(*structDef); + else if (EnumDefinition const* enumDef = dynamic_cast<EnumDefinition const*>(declaration)) + _typeName.annotation().type = make_shared<EnumType>(*enumDef); + else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration)) + _typeName.annotation().type = make_shared<ContractType>(*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<MappingType>(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<IntegerConstantType const*>(length->annotation().type.get()); + if (!lengthType) + fatalTypeError(length->location(), "Invalid array length."); + else + _typeName.annotation().type = make_shared<ArrayType>(DataLocation::Storage, baseType, lengthType->literalValue(nullptr)); + } + else + _typeName.annotation().type = make_shared<ArrayType>(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<ElementaryTypeName const*>(&_typeName)) - type = Type::fromElementaryTypeName(elemTypeName->typeName()); - else if (auto typeName = dynamic_cast<UserDefinedTypeName const*>(&_typeName)) - { - Declaration const* declaration = typeName->annotation().referencedDeclaration; - solAssert(!!declaration, ""); - - if (StructDefinition const* structDef = dynamic_cast<StructDefinition const*>(declaration)) - type = make_shared<StructType>(*structDef); - else if (EnumDefinition const* enumDef = dynamic_cast<EnumDefinition const*>(declaration)) - type = make_shared<EnumType>(*enumDef); - else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration)) - type = make_shared<ContractType>(*contract); - else - fatalTypeError(typeName->location(), "Name has to refer to a struct, enum or contract."); - } - else if (auto mapping = dynamic_cast<Mapping const*>(&_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<MappingType>(keyType, valueType); - } - else if (auto arrayType = dynamic_cast<ArrayTypeName const*>(&_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<IntegerConstantType const*>(length->annotation().type.get()); - if (!lengthType) - fatalTypeError(length->location(), "Invalid array length."); - else - type = make_shared<ArrayType>(DataLocation::Storage, baseType, lengthType->literalValue(nullptr)); - } - else - type = make_shared<ArrayType>(DataLocation::Storage, baseType); - } - - return _typeName.annotation().type = move(type); -} - void ReferencesResolver::typeError(SourceLocation const& _location, string const& _description) { auto err = make_shared<Error>(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); diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 1d2d0258..851266bd 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -356,7 +356,16 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance) " to " + parameterTypes[i]->toString() + " requested." - ); + ); +} + +void TypeChecker::endVisit(UsingForDirective const& _usingFor) +{ + ContractDefinition const* library = dynamic_cast<ContractDefinition const*>( + _usingFor.libraryName().annotation().referencedDeclaration + ); + if (!library || !library->isLibrary()) + typeError(_usingFor.libraryName().location(), "Library name expected."); } bool TypeChecker::visit(StructDefinition const& _struct) @@ -1119,7 +1128,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) for (auto it = possibleMembers.begin(); it != possibleMembers.end();) if ( it->type->category() == Type::Category::Function && - !dynamic_cast<FunctionType const&>(*it->type).canTakeArguments(*argumentTypes) + !dynamic_cast<FunctionType const&>(*it->type).canTakeArguments(*argumentTypes, exprType) ) it = possibleMembers.erase(it); else @@ -1154,6 +1163,15 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) auto& annotation = _memberAccess.annotation(); annotation.referencedDeclaration = possibleMembers.front().declaration; annotation.type = possibleMembers.front().type; + + if (auto funType = dynamic_cast<FunctionType const*>(annotation.type.get())) + if (funType->bound() && !exprType->isImplicitlyConvertibleTo(*funType->selfType())) + typeError( + _memberAccess.location(), + "Function \"" + memberName + "\" cannot be called on an object of type " + + exprType->toString() + " (expected " + funType->selfType()->toString() + ")" + ); + if (exprType->category() == Type::Category::Struct) annotation.isLValue = true; else if (exprType->category() == Type::Category::Array) diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 9563d4a9..7829a23d 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -76,6 +76,7 @@ private: void checkLibraryRequirements(ContractDefinition const& _contract); virtual void endVisit(InheritanceSpecifier const& _inheritance) override; + virtual void endVisit(UsingForDirective const& _usingFor) override; virtual bool visit(StructDefinition const& _struct) override; virtual bool visit(FunctionDefinition const& _function) override; virtual bool visit(VariableDeclaration const& _variable) override; |