diff options
author | Alex Beregszaszi <alex@rtfs.hu> | 2019-01-18 19:36:49 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-18 19:36:49 +0800 |
commit | 7b759866cbcde44915760a416d3e9f78f465adf2 (patch) | |
tree | 56887a5873c343602ee7ba48f5bd782ada730b43 | |
parent | 2ec997e697e306dd54165aad365406ee88c534cb (diff) | |
parent | b7a86a124d658f0723f576e0f447773f3bec148b (diff) | |
download | dexon-solidity-7b759866cbcde44915760a416d3e9f78f465adf2.tar.gz dexon-solidity-7b759866cbcde44915760a416d3e9f78f465adf2.tar.zst dexon-solidity-7b759866cbcde44915760a416d3e9f78f465adf2.zip |
Merge pull request #5817 from ethereum/refactoring
Refactoring in TypeChecker and ContractDefinition
-rw-r--r-- | libsolidity/analysis/SyntaxChecker.cpp | 2 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 43 | ||||
-rw-r--r-- | libsolidity/ast/AST.h | 1 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 2 |
4 files changed, 28 insertions, 20 deletions
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 066b5004..7b8aa0f2 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -262,7 +262,7 @@ bool SyntaxChecker::visit(PlaceholderStatement const&) bool SyntaxChecker::visit(ContractDefinition const& _contract) { - m_isInterface = _contract.contractKind() == ContractDefinition::ContractKind::Interface; + m_isInterface = _contract.isInterface(); ASTString const& contractName = _contract.name(); for (FunctionDefinition const* function: _contract.definedFunctions()) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d038233c..f1a5f7ce 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -236,7 +236,7 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance) auto base = dynamic_cast<ContractDefinition const*>(&dereference(_inheritance.name())); solAssert(base, "Base contract not available."); - if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface) + if (m_scope->isInterface()) m_errorReporter.typeError(_inheritance.location(), "Interfaces cannot inherit."); if (base->isLibrary()) @@ -244,7 +244,7 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance) auto const& arguments = _inheritance.arguments(); TypePointers parameterTypes; - if (base->contractKind() != ContractDefinition::ContractKind::Interface) + if (!base->isInterface()) // Interfaces do not have constructors, so there are zero parameters. parameterTypes = ContractType(*base).newExpressionType()->parameterTypes(); @@ -331,33 +331,40 @@ bool TypeChecker::visit(FunctionDefinition const& _function) if (!_function.isConstructor() && !_function.isFallback() && !_function.isPartOfExternalInterface()) m_errorReporter.typeError(_function.location(), "Internal functions cannot be payable."); } - for (ASTPointer<VariableDeclaration> const& var: _function.parameters() + _function.returnParameters()) - { - if (type(*var)->category() == Type::Category::Mapping) + auto checkArgumentAndReturnParameter = [&](VariableDeclaration const& var) { + if (type(var)->category() == Type::Category::Mapping) { - if (!type(*var)->dataStoredIn(DataLocation::Storage)) - m_errorReporter.typeError(var->location(), "Mapping types can only have a data location of \"storage\"." ); + if (!type(var)->dataStoredIn(DataLocation::Storage)) + m_errorReporter.typeError(var.location(), "Mapping types can only have a data location of \"storage\"." ); else if (!isLibraryFunction && _function.isPublic()) - m_errorReporter.typeError(var->location(), "Mapping types for parameters or return variables can only be used in internal or library functions."); + m_errorReporter.typeError(var.location(), "Mapping types for parameters or return variables can only be used in internal or library functions."); } else { - if (!type(*var)->canLiveOutsideStorage() && _function.isPublic()) - m_errorReporter.typeError(var->location(), "Type is required to live outside storage."); - if (_function.isPublic() && !(type(*var)->interfaceType(isLibraryFunction))) - m_errorReporter.fatalTypeError(var->location(), "Internal or recursive type is not allowed for public or external functions."); + if (!type(var)->canLiveOutsideStorage() && _function.isPublic()) + m_errorReporter.typeError(var.location(), "Type is required to live outside storage."); + if (_function.isPublic() && !(type(var)->interfaceType(isLibraryFunction))) + m_errorReporter.fatalTypeError(var.location(), "Internal or recursive type is not allowed for public or external functions."); } if ( _function.isPublic() && !_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) && - !typeSupportedByOldABIEncoder(*type(*var)) + !typeSupportedByOldABIEncoder(*type(var)) ) m_errorReporter.typeError( - var->location(), + var.location(), "This type is only supported in the new experimental ABI encoder. " "Use \"pragma experimental ABIEncoderV2;\" to enable the feature." ); - + }; + for (ASTPointer<VariableDeclaration> const& var: _function.parameters()) + { + checkArgumentAndReturnParameter(*var); + var->accept(*this); + } + for (ASTPointer<VariableDeclaration> const& var: _function.returnParameters()) + { + checkArgumentAndReturnParameter(*var); var->accept(*this); } set<Declaration const*> modifiers; @@ -378,7 +385,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function) else modifiers.insert(decl); } - if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface) + if (m_scope->isInterface()) { if (_function.isImplemented()) m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot have an implementation."); @@ -407,7 +414,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) // * a function's input/output parameters, // * or inside of a struct definition. if ( - m_scope->contractKind() == ContractDefinition::ContractKind::Interface + m_scope->isInterface() && !_variable.isCallableParameter() && !m_insideStruct ) @@ -1906,7 +1913,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression) if (!contract) m_errorReporter.fatalTypeError(_newExpression.location(), "Identifier is not a contract."); - if (contract->contractKind() == ContractDefinition::ContractKind::Interface) + if (contract->isInterface()) m_errorReporter.fatalTypeError(_newExpression.location(), "Cannot instantiate an interface."); if (!contract->annotation().unimplementedFunctions.empty()) { diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index cd986050..f6fdc441 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -394,6 +394,7 @@ public: std::vector<FunctionDefinition const*> definedFunctions() const { return filteredNodes<FunctionDefinition>(m_subNodes); } std::vector<EventDefinition const*> events() const { return filteredNodes<EventDefinition>(m_subNodes); } std::vector<EventDefinition const*> const& interfaceEvents() const; + bool isInterface() const { return m_contractKind == ContractKind::Interface; } bool isLibrary() const { return m_contractKind == ContractKind::Library; } /// @returns a map of canonical function signatures to FunctionDefinitions diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 081c7fb6..3a8c9878 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2525,7 +2525,7 @@ FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _c strings parameterNames; StateMutability stateMutability = StateMutability::NonPayable; - solAssert(_contract.contractKind() != ContractDefinition::ContractKind::Interface, ""); + solAssert(!_contract.isInterface(), ""); if (constructor) { |