aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/analysis
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-11-30 23:06:44 +0800
committerchriseth <c@ethdev.com>2015-11-30 23:06:44 +0800
commite9c7837c154482a72c8519fbdc9376693ce9a1d5 (patch)
tree1985b57b4e221fe4e4b5cc14a5049b8c0c46ce6c /libsolidity/analysis
parenta8736b7b271dac117f15164cf4d2dfabcdd2c6fd (diff)
parentf9e52c9db1ef23000f5721a462aba3fa8d681749 (diff)
downloaddexon-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.h4
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp140
-rw-r--r--libsolidity/analysis/ReferencesResolver.h8
-rw-r--r--libsolidity/analysis/TypeChecker.cpp22
-rw-r--r--libsolidity/analysis/TypeChecker.h1
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;