aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2019-01-18 19:36:49 +0800
committerGitHub <noreply@github.com>2019-01-18 19:36:49 +0800
commit7b759866cbcde44915760a416d3e9f78f465adf2 (patch)
tree56887a5873c343602ee7ba48f5bd782ada730b43
parent2ec997e697e306dd54165aad365406ee88c534cb (diff)
parentb7a86a124d658f0723f576e0f447773f3bec148b (diff)
downloaddexon-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.cpp2
-rw-r--r--libsolidity/analysis/TypeChecker.cpp43
-rw-r--r--libsolidity/ast/AST.h1
-rw-r--r--libsolidity/ast/Types.cpp2
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)
{