aboutsummaryrefslogtreecommitdiffstats
path: root/NameAndTypeResolver.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-04-15 23:40:50 +0800
committerchriseth <c@ethdev.com>2015-04-15 23:40:50 +0800
commit0c69d5fdcd3286f47c81dbcbcfb8802861eab8b5 (patch)
treef78c665e6084300b939cc4cfcebb97d3bd44d9f5 /NameAndTypeResolver.cpp
parent158795e48f4285d713b11f78cdd04de8c6d1f667 (diff)
downloaddexon-solidity-0c69d5fdcd3286f47c81dbcbcfb8802861eab8b5.tar.gz
dexon-solidity-0c69d5fdcd3286f47c81dbcbcfb8802861eab8b5.tar.zst
dexon-solidity-0c69d5fdcd3286f47c81dbcbcfb8802861eab8b5.zip
Fixed function overloads.
Added tests, disallowed non-calling usage of non-unique function references.
Diffstat (limited to 'NameAndTypeResolver.cpp')
-rw-r--r--NameAndTypeResolver.cpp80
1 files changed, 67 insertions, 13 deletions
diff --git a/NameAndTypeResolver.cpp b/NameAndTypeResolver.cpp
index c787ae6b..1c527b89 100644
--- a/NameAndTypeResolver.cpp
+++ b/NameAndTypeResolver.cpp
@@ -53,8 +53,9 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
m_currentScope = &m_scopes[&_contract];
linearizeBaseContracts(_contract);
+ // we first import non-functions only as we do not yet know the argument types
for (ContractDefinition const* base: _contract.getLinearizedBaseContracts())
- importInheritedScope(*base);
+ importInheritedScope(*base, false); // import non-functions
for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs())
ReferencesResolver resolver(*structDef, *this, &_contract, nullptr);
@@ -64,6 +65,8 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
ReferencesResolver resolver(*variable, *this, &_contract, nullptr);
for (ASTPointer<EventDefinition> const& event: _contract.getEvents())
ReferencesResolver resolver(*event, *this, &_contract, nullptr);
+
+ // these can contain code, only resolve parameters for now
for (ASTPointer<ModifierDefinition> const& modifier: _contract.getFunctionModifiers())
{
m_currentScope = &m_scopes[modifier.get()];
@@ -75,6 +78,28 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
ReferencesResolver referencesResolver(*function, *this, &_contract,
function->getReturnParameterList().get());
}
+
+ m_currentScope = &m_scopes[&_contract];
+ for (ContractDefinition const* base: _contract.getLinearizedBaseContracts())
+ importInheritedScope(*base, true); // import functions
+
+ // now resolve references inside the code
+ for (ASTPointer<ModifierDefinition> const& modifier: _contract.getFunctionModifiers())
+ {
+ m_currentScope = &m_scopes[modifier.get()];
+ ReferencesResolver resolver(*modifier, *this, &_contract, nullptr, true);
+ }
+ for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
+ {
+ m_currentScope = &m_scopes[function.get()];
+ ReferencesResolver referencesResolver(
+ *function,
+ *this,
+ &_contract,
+ function->getReturnParameterList().get(),
+ true
+ );
+ }
}
void NameAndTypeResolver::checkTypeRequirements(ContractDefinition& _contract)
@@ -90,7 +115,7 @@ void NameAndTypeResolver::updateDeclaration(Declaration const& _declaration)
solAssert(_declaration.getScope() == nullptr, "Updated declaration outside global scope.");
}
-std::set<Declaration const*> NameAndTypeResolver::resolveName(ASTString const& _name, Declaration const* _scope) const
+set<Declaration const*> NameAndTypeResolver::resolveName(ASTString const& _name, Declaration const* _scope) const
{
auto iterator = m_scopes.find(_scope);
if (iterator == end(m_scopes))
@@ -98,21 +123,43 @@ std::set<Declaration const*> NameAndTypeResolver::resolveName(ASTString const& _
return iterator->second.resolveName(_name, false);
}
-std::set<Declaration const*> NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name, bool _recursive)
+set<Declaration const*> NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name, bool _recursive)
{
return m_currentScope->resolveName(_name, _recursive);
}
-void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base)
+void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base, bool _importFunctions)
{
auto iterator = m_scopes.find(&_base);
solAssert(iterator != end(m_scopes), "");
for (auto const& nameAndDeclaration: iterator->second.getDeclarations())
for (auto const& declaration: nameAndDeclaration.second)
// Import if it was declared in the base, is not the constructor and is visible in derived classes
- if (declaration->getScope() == &_base && declaration->getName() != _base.getName() &&
- declaration->isVisibleInDerivedContracts())
+ if (declaration->getScope() == &_base && declaration->isVisibleInDerivedContracts())
+ {
+ auto function = dynamic_cast<FunctionDefinition const*>(declaration);
+ if ((function == nullptr) == _importFunctions)
+ continue;
+ if (!!function)
+ {
+ FunctionType functionType(*function);
+ // only import if a function with the same arguments does not exist yet
+ bool functionWithEqualArgumentsFound = false;
+ for (auto knownDeclaration: m_currentScope->resolveName(nameAndDeclaration.first))
+ {
+ auto knownFunction = dynamic_cast<FunctionDefinition const*>(knownDeclaration);
+ if (!knownFunction)
+ continue; // this is not legal, but will be caught later
+ if (!FunctionType(*knownFunction).hasEqualArgumentTypes(functionType))
+ continue;
+ functionWithEqualArgumentsFound = true;
+ break;
+ }
+ if (functionWithEqualArgumentsFound)
+ continue;
+ }
m_currentScope->registerDeclaration(*declaration);
+ }
}
void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract) const
@@ -123,8 +170,7 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract)
for (ASTPointer<InheritanceSpecifier> const& baseSpecifier: _contract.getBaseContracts())
{
ASTPointer<Identifier> baseName = baseSpecifier->getName();
- ContractDefinition const* base = dynamic_cast<ContractDefinition const*>(
- baseName->getReferencedDeclaration());
+ auto base = dynamic_cast<ContractDefinition const*>(&baseName->getReferencedDeclaration());
if (!base)
BOOST_THROW_EXCEPTION(baseName->createTypeError("Contract expected."));
// "push_front" has the effect that bases mentioned later can overwrite members of bases
@@ -316,11 +362,19 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
enterNewSubScope(_declaration);
}
-ReferencesResolver::ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver,
- ContractDefinition const* _currentContract,
- ParameterList const* _returnParameters, bool _allowLazyTypes):
- m_resolver(_resolver), m_currentContract(_currentContract),
- m_returnParameters(_returnParameters), m_allowLazyTypes(_allowLazyTypes)
+ReferencesResolver::ReferencesResolver(
+ ASTNode& _root,
+ NameAndTypeResolver& _resolver,
+ ContractDefinition const* _currentContract,
+ ParameterList const* _returnParameters,
+ bool _resolveInsideCode,
+ bool _allowLazyTypes
+):
+ m_resolver(_resolver),
+ m_currentContract(_currentContract),
+ m_returnParameters(_returnParameters),
+ m_resolveInsideCode(_resolveInsideCode),
+ m_allowLazyTypes(_allowLazyTypes)
{
_root.accept(*this);
}