aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp96
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.h9
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp27
-rw-r--r--libsolidity/analysis/ReferencesResolver.h9
-rw-r--r--libsolidity/analysis/SyntaxChecker.cpp4
-rw-r--r--libsolidity/analysis/SyntaxChecker.h2
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp2
7 files changed, 87 insertions, 62 deletions
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp
index b0a82715..2791fed7 100644
--- a/libsolidity/analysis/NameAndTypeResolver.cpp
+++ b/libsolidity/analysis/NameAndTypeResolver.cpp
@@ -132,68 +132,64 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
return !error;
}
-bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
+bool NameAndTypeResolver::resolveNamesAndTypes(ASTNode& _node, bool _resolveInsideCode)
{
+ bool success = true;
try
{
- m_currentScope = m_scopes[_contract.scope()].get();
- solAssert(!!m_currentScope, "");
+ if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(&_node))
+ {
+ m_currentScope = m_scopes[contract->scope()].get();
+ solAssert(!!m_currentScope, "");
- ReferencesResolver resolver(m_errors, *this, nullptr);
- bool success = true;
- for (ASTPointer<InheritanceSpecifier> const& baseContract: _contract.baseContracts())
- if (!resolver.resolve(*baseContract))
- success = false;
+ for (ASTPointer<InheritanceSpecifier> const& baseContract: contract->baseContracts())
+ if (!resolveNamesAndTypes(*baseContract, false))
+ success = false;
- m_currentScope = m_scopes[&_contract].get();
+ m_currentScope = m_scopes[contract].get();
- if (success)
- {
- linearizeBaseContracts(_contract);
- vector<ContractDefinition const*> properBases(
- ++_contract.annotation().linearizedBaseContracts.begin(),
- _contract.annotation().linearizedBaseContracts.end()
- );
-
- for (ContractDefinition const* base: properBases)
- importInheritedScope(*base);
- }
+ if (success)
+ {
+ linearizeBaseContracts(*contract);
+ vector<ContractDefinition const*> properBases(
+ ++contract->annotation().linearizedBaseContracts.begin(),
+ contract->annotation().linearizedBaseContracts.end()
+ );
- // these can contain code, only resolve parameters for now
- for (ASTPointer<ASTNode> const& node: _contract.subNodes())
- {
- m_currentScope = m_scopes[m_scopes.count(node.get()) ? node.get() : &_contract].get();
- if (!resolver.resolve(*node))
- success = false;
- }
+ for (ContractDefinition const* base: properBases)
+ importInheritedScope(*base);
+ }
- if (!success)
- return false;
+ // these can contain code, only resolve parameters for now
+ for (ASTPointer<ASTNode> const& node: contract->subNodes())
+ {
+ m_currentScope = m_scopes[contract].get();
+ if (!resolveNamesAndTypes(*node, false))
+ success = false;
+ }
- m_currentScope = m_scopes[&_contract].get();
+ if (!success)
+ return false;
- // now resolve references inside the code
- for (ModifierDefinition const* modifier: _contract.functionModifiers())
- {
- m_currentScope = m_scopes[modifier].get();
- ReferencesResolver resolver(m_errors, *this, nullptr, true);
- if (!resolver.resolve(*modifier))
- success = false;
- }
+ if (!_resolveInsideCode)
+ return success;
- for (FunctionDefinition const* function: _contract.definedFunctions())
+ m_currentScope = m_scopes[contract].get();
+
+ // now resolve references inside the code
+ for (ASTPointer<ASTNode> const& node: contract->subNodes())
+ {
+ m_currentScope = m_scopes[contract].get();
+ if (!resolveNamesAndTypes(*node, true))
+ success = false;
+ }
+ }
+ else
{
- m_currentScope = m_scopes[function].get();
- if (!ReferencesResolver(
- m_errors,
- *this,
- function->returnParameterList().get(),
- true
- ).resolve(*function))
- success = false;
+ if (m_scopes.count(&_node))
+ m_currentScope = m_scopes[&_node].get();
+ return ReferencesResolver(m_errors, *this, _resolveInsideCode).resolve(_node);
}
- if (!success)
- return false;
}
catch (FatalError const&)
{
@@ -201,7 +197,7 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
throw; // Something is weird here, rather throw again.
return false;
}
- return true;
+ return success;
}
bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration)
diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h
index 68c3ffa1..fb018d74 100644
--- a/libsolidity/analysis/NameAndTypeResolver.h
+++ b/libsolidity/analysis/NameAndTypeResolver.h
@@ -48,9 +48,12 @@ public:
bool registerDeclarations(SourceUnit& _sourceUnit);
/// Applies the effect of import directives.
bool performImports(SourceUnit& _sourceUnit, std::map<std::string, SourceUnit const*> const& _sourceUnits);
- /// Resolves all names and types referenced from the given contract.
+ /// Resolves all names and types referenced from the given AST Node.
+ /// This is usually only called at the contract level, but with a bit of care, it can also
+ /// be called at deeper levels.
+ /// @param _avoidCode if false, does not descend into nodes that contain code.
/// @returns false in case of error.
- bool resolveNamesAndTypes(ContractDefinition& _contract);
+ bool resolveNamesAndTypes(ASTNode& _node, bool _resolveInsideCode = true);
/// Updates the given global declaration (used for "this"). Not to be used with declarations
/// that create their own scope.
/// @returns false in case of error.
@@ -77,8 +80,6 @@ public:
);
private:
- void reset();
-
/// Imports all members declared directly in the given contract (i.e. does not import inherited members)
/// into the current scope if they are not present already.
void importInheritedScope(ContractDefinition const& _base);
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index d589f4a0..c06181d8 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -65,6 +65,30 @@ bool ReferencesResolver::visit(ElementaryTypeName const& _typeName)
return true;
}
+bool ReferencesResolver::visit(FunctionDefinition const& _functionDefinition)
+{
+ m_returnParameters.push_back(_functionDefinition.returnParameterList().get());
+ return true;
+}
+
+void ReferencesResolver::endVisit(FunctionDefinition const&)
+{
+ solAssert(!m_returnParameters.empty(), "");
+ m_returnParameters.pop_back();
+}
+
+bool ReferencesResolver::visit(ModifierDefinition const&)
+{
+ m_returnParameters.push_back(nullptr);
+ return true;
+}
+
+void ReferencesResolver::endVisit(ModifierDefinition const&)
+{
+ solAssert(!m_returnParameters.empty(), "");
+ m_returnParameters.pop_back();
+}
+
void ReferencesResolver::endVisit(UserDefinedTypeName const& _typeName)
{
Declaration const* declaration = m_resolver.pathFromCurrentScope(_typeName.namePath());
@@ -161,7 +185,8 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
bool ReferencesResolver::visit(Return const& _return)
{
- _return.annotation().functionReturnParameters = m_returnParameters;
+ solAssert(!m_returnParameters.empty(), "");
+ _return.annotation().functionReturnParameters = m_returnParameters.back();
return true;
}
diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h
index caa3a78f..23ac6b07 100644
--- a/libsolidity/analysis/ReferencesResolver.h
+++ b/libsolidity/analysis/ReferencesResolver.h
@@ -45,12 +45,10 @@ public:
ReferencesResolver(
ErrorList& _errors,
NameAndTypeResolver& _resolver,
- ParameterList const* _returnParameters,
bool _resolveInsideCode = false
):
m_errors(_errors),
m_resolver(_resolver),
- m_returnParameters(_returnParameters),
m_resolveInsideCode(_resolveInsideCode)
{}
@@ -61,6 +59,10 @@ private:
virtual bool visit(Block const&) override { return m_resolveInsideCode; }
virtual bool visit(Identifier const& _identifier) override;
virtual bool visit(ElementaryTypeName const& _typeName) override;
+ virtual bool visit(FunctionDefinition const& _functionDefinition) override;
+ virtual void endVisit(FunctionDefinition const& _functionDefinition) override;
+ virtual bool visit(ModifierDefinition const& _modifierDefinition) override;
+ virtual void endVisit(ModifierDefinition const& _modifierDefinition) override;
virtual void endVisit(UserDefinedTypeName const& _typeName) override;
virtual void endVisit(FunctionTypeName const& _typeName) override;
virtual void endVisit(Mapping const& _typeName) override;
@@ -83,7 +85,8 @@ private:
ErrorList& m_errors;
NameAndTypeResolver& m_resolver;
- ParameterList const* m_returnParameters;
+ /// Stack of return parameters.
+ std::vector<ParameterList const*> m_returnParameters;
bool const m_resolveInsideCode;
bool m_errorOccurred = false;
};
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp
index 0a4943fe..89014133 100644
--- a/libsolidity/analysis/SyntaxChecker.cpp
+++ b/libsolidity/analysis/SyntaxChecker.cpp
@@ -26,9 +26,9 @@ using namespace dev;
using namespace dev::solidity;
-bool SyntaxChecker::checkSyntax(SourceUnit const& _sourceUnit)
+bool SyntaxChecker::checkSyntax(ASTNode const& _astRoot)
{
- _sourceUnit.accept(*this);
+ _astRoot.accept(*this);
return Error::containsOnlyWarnings(m_errors);
}
diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h
index c24bae09..308e128b 100644
--- a/libsolidity/analysis/SyntaxChecker.h
+++ b/libsolidity/analysis/SyntaxChecker.h
@@ -39,7 +39,7 @@ public:
/// @param _errors the reference to the list of errors and warnings to add them found during type checking.
SyntaxChecker(ErrorList& _errors): m_errors(_errors) {}
- bool checkSyntax(SourceUnit const& _sourceUnit);
+ bool checkSyntax(ASTNode const& _astRoot);
private:
/// Adds a new error to the list of errors.
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 0151d244..29856d31 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -1080,7 +1080,7 @@ BOOST_AUTO_TEST_CASE(modifier_returns_value)
modifier mod(uint a) { _; return 7; }
}
)";
- CHECK_ERROR(text, TypeError, "");
+ CHECK_ERROR(text, TypeError, "Return arguments not allowed.");
}
BOOST_AUTO_TEST_CASE(state_variable_accessors)