aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/analysis/DocStringAnalyser.cpp7
-rw-r--r--libsolidity/analysis/DocStringAnalyser.h6
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp131
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.h40
-rw-r--r--libsolidity/analysis/PostTypeChecker.cpp19
-rw-r--r--libsolidity/analysis/PostTypeChecker.h6
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp24
-rw-r--r--libsolidity/analysis/ReferencesResolver.h12
-rw-r--r--libsolidity/analysis/StaticAnalyzer.cpp27
-rw-r--r--libsolidity/analysis/StaticAnalyzer.h6
-rw-r--r--libsolidity/analysis/SyntaxChecker.cpp41
-rw-r--r--libsolidity/analysis/SyntaxChecker.h7
-rw-r--r--libsolidity/analysis/TypeChecker.cpp330
-rw-r--r--libsolidity/analysis/TypeChecker.h14
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp5
-rw-r--r--libsolidity/formal/Why3Translator.cpp30
-rw-r--r--libsolidity/formal/Why3Translator.h16
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp153
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.h9
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp4
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.h8
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp6
-rw-r--r--libsolidity/inlineasm/AsmParser.h2
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.cpp33
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.h8
-rw-r--r--libsolidity/inlineasm/AsmStack.cpp19
-rw-r--r--libsolidity/inlineasm/AsmStack.h10
-rw-r--r--libsolidity/interface/AssemblyStack.cpp8
-rw-r--r--libsolidity/interface/AssemblyStack.h5
-rw-r--r--libsolidity/interface/CompilerStack.cpp48
-rw-r--r--libsolidity/interface/CompilerStack.h14
-rw-r--r--libsolidity/interface/ErrorReporter.cpp186
-rw-r--r--libsolidity/interface/ErrorReporter.h106
-rw-r--r--libsolidity/parsing/DocStringParser.cpp9
-rw-r--r--libsolidity/parsing/DocStringParser.h7
-rw-r--r--libsolidity/parsing/Parser.cpp6
-rw-r--r--libsolidity/parsing/Parser.h2
-rw-r--r--libsolidity/parsing/ParserBase.cpp11
-rw-r--r--libsolidity/parsing/ParserBase.h6
39 files changed, 718 insertions, 663 deletions
diff --git a/libsolidity/analysis/DocStringAnalyser.cpp b/libsolidity/analysis/DocStringAnalyser.cpp
index 58261144..6a8fa08e 100644
--- a/libsolidity/analysis/DocStringAnalyser.cpp
+++ b/libsolidity/analysis/DocStringAnalyser.cpp
@@ -23,6 +23,7 @@
#include <libsolidity/analysis/DocStringAnalyser.h>
#include <libsolidity/ast/AST.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/parsing/DocStringParser.h>
using namespace std;
@@ -110,7 +111,7 @@ void DocStringAnalyser::parseDocStrings(
DocStringParser parser;
if (_node.documentation() && !_node.documentation()->empty())
{
- if (!parser.parse(*_node.documentation(), m_errors))
+ if (!parser.parse(*_node.documentation(), m_errorReporter))
m_errorOccured = true;
_annotation.docTags = parser.tags();
}
@@ -121,8 +122,6 @@ void DocStringAnalyser::parseDocStrings(
void DocStringAnalyser::appendError(string const& _description)
{
- auto err = make_shared<Error>(Error::Type::DocstringParsingError);
- *err << errinfo_comment(_description);
- m_errors.push_back(err);
m_errorOccured = true;
+ m_errorReporter.docstringParsingError(_description);
}
diff --git a/libsolidity/analysis/DocStringAnalyser.h b/libsolidity/analysis/DocStringAnalyser.h
index bfc8befc..e871cb60 100644
--- a/libsolidity/analysis/DocStringAnalyser.h
+++ b/libsolidity/analysis/DocStringAnalyser.h
@@ -30,6 +30,8 @@ namespace dev
namespace solidity
{
+class ErrorReporter;
+
/**
* Parses and analyses the doc strings.
* Stores the parsing results in the AST annotations and reports errors.
@@ -37,7 +39,7 @@ namespace solidity
class DocStringAnalyser: private ASTConstVisitor
{
public:
- DocStringAnalyser(ErrorList& _errors): m_errors(_errors) {}
+ DocStringAnalyser(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {}
bool analyseDocStrings(SourceUnit const& _sourceUnit);
private:
@@ -64,7 +66,7 @@ private:
void appendError(std::string const& _description);
bool m_errorOccured = false;
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
};
}
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp
index 336dc894..2742dcf2 100644
--- a/libsolidity/analysis/NameAndTypeResolver.cpp
+++ b/libsolidity/analysis/NameAndTypeResolver.cpp
@@ -24,7 +24,7 @@
#include <libsolidity/ast/AST.h>
#include <libsolidity/analysis/TypeChecker.h>
-#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/interface/ErrorReporter.h>
using namespace std;
@@ -36,10 +36,10 @@ namespace solidity
NameAndTypeResolver::NameAndTypeResolver(
vector<Declaration const*> const& _globals,
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
- ErrorList& _errors
+ ErrorReporter& _errorReporter
) :
m_scopes(_scopes),
- m_errors(_errors)
+ m_errorReporter(_errorReporter)
{
if (!m_scopes[nullptr])
m_scopes[nullptr].reset(new DeclarationContainer());
@@ -52,11 +52,11 @@ bool NameAndTypeResolver::registerDeclarations(ASTNode& _sourceUnit, ASTNode con
// The helper registers all declarations in m_scopes as a side-effect of its construction.
try
{
- DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errors, _currentScope);
+ DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errorReporter, _currentScope);
}
catch (FatalError const&)
{
- if (m_errors.empty())
+ if (m_errorReporter.errors().empty())
throw; // Something is weird here, rather throw again.
return false;
}
@@ -73,7 +73,7 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
string const& path = imp->annotation().absolutePath;
if (!_sourceUnits.count(path))
{
- reportDeclarationError(
+ m_errorReporter.declarationError(
imp->location(),
"Import \"" + path + "\" (referenced as \"" + imp->path() + "\") not found."
);
@@ -88,7 +88,7 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
auto declarations = scope->second->resolveName(alias.first->name(), false);
if (declarations.empty())
{
- reportDeclarationError(
+ m_errorReporter.declarationError(
imp->location(),
"Declaration \"" +
alias.first->name() +
@@ -106,7 +106,7 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
ASTString const* name = alias.second ? alias.second.get() : &declaration->name();
if (!target.registerDeclaration(*declaration, name))
{
- reportDeclarationError(
+ m_errorReporter.declarationError(
imp->location(),
"Identifier \"" + *name + "\" already declared."
);
@@ -119,7 +119,7 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
for (auto const& declaration: nameAndDeclaration.second)
if (!target.registerDeclaration(*declaration, &nameAndDeclaration.first))
{
- reportDeclarationError(
+ m_errorReporter.declarationError(
imp->location(),
"Identifier \"" + nameAndDeclaration.first + "\" already declared."
);
@@ -137,7 +137,7 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ASTNode& _node, bool _resolveInsi
}
catch (FatalError const&)
{
- if (m_errors.empty())
+ if (m_errorReporter.errors().empty())
throw; // Something is weird here, rather throw again.
return false;
}
@@ -152,7 +152,7 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration)
}
catch (FatalError const&)
{
- if (m_errors.empty())
+ if (m_errorReporter.errors().empty())
throw; // Something is weird here, rather throw again.
return false;
}
@@ -214,7 +214,7 @@ vector<Declaration const*> NameAndTypeResolver::cleanedDeclarations(
for (auto parameter: functionType->parameterTypes() + functionType->returnParameterTypes())
if (!parameter)
- reportFatalDeclarationError(_identifier.location(), "Function type can not be used in this context.");
+ m_errorReporter.fatalDeclarationError(_identifier.location(), "Function type can not be used in this context.");
if (uniqueFunctions.end() == find_if(
uniqueFunctions.begin(),
@@ -290,7 +290,7 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res
{
if (m_scopes.count(&_node))
m_currentScope = m_scopes[&_node].get();
- return ReferencesResolver(m_errors, *this, _resolveInsideCode).resolve(_node);
+ return ReferencesResolver(m_errorReporter, *this, _resolveInsideCode).resolve(_node);
}
}
@@ -328,11 +328,10 @@ void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base)
secondDeclarationLocation = declaration->location();
}
- reportDeclarationError(
+ m_errorReporter.declarationError(
secondDeclarationLocation,
- "Identifier already declared.",
- firstDeclarationLocation,
- "The previous declaration is here:"
+ SecondarySourceLocation().append("The previous declaration is here:", firstDeclarationLocation),
+ "Identifier already declared."
);
}
}
@@ -347,19 +346,19 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract)
UserDefinedTypeName const& baseName = baseSpecifier->name();
auto base = dynamic_cast<ContractDefinition const*>(baseName.annotation().referencedDeclaration);
if (!base)
- reportFatalTypeError(baseName.createTypeError("Contract expected."));
+ m_errorReporter.fatalTypeError(baseName.location(), "Contract expected.");
// "push_front" has the effect that bases mentioned later can overwrite members of bases
// mentioned earlier
input.back().push_front(base);
vector<ContractDefinition const*> const& basesBases = base->annotation().linearizedBaseContracts;
if (basesBases.empty())
- reportFatalTypeError(baseName.createTypeError("Definition of base has to precede definition of derived contract"));
+ m_errorReporter.fatalTypeError(baseName.location(), "Definition of base has to precede definition of derived contract");
input.push_front(list<ContractDefinition const*>(basesBases.begin(), basesBases.end()));
}
input.back().push_front(&_contract);
vector<ContractDefinition const*> result = cThreeMerge(input);
if (result.empty())
- reportFatalTypeError(_contract.createTypeError("Linearization of inheritance graph impossible"));
+ m_errorReporter.fatalTypeError(_contract.location(), "Linearization of inheritance graph impossible");
_contract.annotation().linearizedBaseContracts = result;
_contract.annotation().contractDependencies.insert(result.begin() + 1, result.end());
}
@@ -415,61 +414,15 @@ vector<_T const*> NameAndTypeResolver::cThreeMerge(list<list<_T const*>>& _toMer
return result;
}
-void NameAndTypeResolver::reportDeclarationError(
- SourceLocation _sourceLoction,
- string const& _description,
- SourceLocation _secondarySourceLocation,
- string const& _secondaryDescription
-)
-{
- auto err = make_shared<Error>(Error::Type::DeclarationError); // todo remove Error?
- *err <<
- errinfo_sourceLocation(_sourceLoction) <<
- errinfo_comment(_description) <<
- errinfo_secondarySourceLocation(
- SecondarySourceLocation().append(_secondaryDescription, _secondarySourceLocation)
- );
-
- m_errors.push_back(err);
-}
-
-void NameAndTypeResolver::reportDeclarationError(SourceLocation _sourceLocation, string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::DeclarationError); // todo remove Error?
- *err << errinfo_sourceLocation(_sourceLocation) << errinfo_comment(_description);
-
- m_errors.push_back(err);
-}
-
-void NameAndTypeResolver::reportFatalDeclarationError(
- SourceLocation _sourceLocation,
- string const& _description
-)
-{
- reportDeclarationError(_sourceLocation, _description);
- BOOST_THROW_EXCEPTION(FatalError());
-}
-
-void NameAndTypeResolver::reportTypeError(Error const& _e)
-{
- m_errors.push_back(make_shared<Error>(_e));
-}
-
-void NameAndTypeResolver::reportFatalTypeError(Error const& _e)
-{
- reportTypeError(_e);
- BOOST_THROW_EXCEPTION(FatalError());
-}
-
DeclarationRegistrationHelper::DeclarationRegistrationHelper(
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
ASTNode& _astRoot,
- ErrorList& _errors,
+ ErrorReporter& _errorReporter,
ASTNode const* _currentScope
):
m_scopes(_scopes),
m_currentScope(_currentScope),
- m_errors(_errors)
+ m_errorReporter(_errorReporter)
{
_astRoot.accept(*this);
solAssert(m_currentScope == _currentScope, "Scopes not correctly closed.");
@@ -633,11 +586,10 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
secondDeclarationLocation = _declaration.location();
}
- declarationError(
+ m_errorReporter.declarationError(
secondDeclarationLocation,
- "Identifier already declared.",
- firstDeclarationLocation,
- "The previous declaration is here:"
+ SecondarySourceLocation().append("The previous declaration is here:", firstDeclarationLocation),
+ "Identifier already declared."
);
}
@@ -665,40 +617,5 @@ string DeclarationRegistrationHelper::currentCanonicalName() const
return ret;
}
-void DeclarationRegistrationHelper::declarationError(
- SourceLocation _sourceLocation,
- string const& _description,
- SourceLocation _secondarySourceLocation,
- string const& _secondaryDescription
-)
-{
- auto err = make_shared<Error>(Error::Type::DeclarationError);
- *err <<
- errinfo_sourceLocation(_sourceLocation) <<
- errinfo_comment(_description) <<
- errinfo_secondarySourceLocation(
- SecondarySourceLocation().append(_secondaryDescription, _secondarySourceLocation)
- );
-
- m_errors.push_back(err);
-}
-
-void DeclarationRegistrationHelper::declarationError(SourceLocation _sourceLocation, string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::DeclarationError);
- *err << errinfo_sourceLocation(_sourceLocation) << errinfo_comment(_description);
-
- m_errors.push_back(err);
-}
-
-void DeclarationRegistrationHelper::fatalDeclarationError(
- SourceLocation _sourceLocation,
- string const& _description
-)
-{
- declarationError(_sourceLocation, _description);
- BOOST_THROW_EXCEPTION(FatalError());
-}
-
}
}
diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h
index 038a887b..0441867d 100644
--- a/libsolidity/analysis/NameAndTypeResolver.h
+++ b/libsolidity/analysis/NameAndTypeResolver.h
@@ -35,6 +35,8 @@ namespace dev
namespace solidity
{
+class ErrorReporter;
+
/**
* Resolves name references, typenames and sets the (explicitly given) types for all variable
* declarations.
@@ -48,7 +50,7 @@ public:
NameAndTypeResolver(
std::vector<Declaration const*> const& _globals,
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes,
- ErrorList& _errors
+ ErrorReporter& _errorReporter
);
/// Registers all declarations found in the AST node, usually a source unit.
/// @returns false in case of error.
@@ -103,24 +105,6 @@ private:
template <class _T>
static std::vector<_T const*> cThreeMerge(std::list<std::list<_T const*>>& _toMerge);
- // creates the Declaration error and adds it in the errors list
- void reportDeclarationError(
- SourceLocation _sourceLoction,
- std::string const& _description,
- SourceLocation _secondarySourceLocation,
- std::string const& _secondaryDescription
- );
- // creates the Declaration error and adds it in the errors list
- void reportDeclarationError(SourceLocation _sourceLocation, std::string const& _description);
- // creates the Declaration error and adds it in the errors list and throws FatalError
- void reportFatalDeclarationError(SourceLocation _sourceLocation, std::string const& _description);
-
- // creates the Declaration error and adds it in the errors list
- void reportTypeError(Error const& _e);
- // creates the Declaration error and adds it in the errors list and throws FatalError
- void reportFatalTypeError(Error const& _e);
-
-
/// Maps nodes declaring a scope to scopes, i.e. ContractDefinition and FunctionDeclaration,
/// where nullptr denotes the global scope. Note that structs are not scope since they do
/// not contain code.
@@ -128,7 +112,7 @@ private:
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& m_scopes;
DeclarationContainer* m_currentScope = nullptr;
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
};
/**
@@ -145,7 +129,7 @@ public:
DeclarationRegistrationHelper(
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes,
ASTNode& _astRoot,
- ErrorList& _errors,
+ ErrorReporter& _errorReporter,
ASTNode const* _currentScope = nullptr
);
@@ -175,23 +159,11 @@ private:
/// @returns the canonical name of the current scope.
std::string currentCanonicalName() const;
- // creates the Declaration error and adds it in the errors list
- void declarationError(
- SourceLocation _sourceLocation,
- std::string const& _description,
- SourceLocation _secondarySourceLocation,
- std::string const& _secondaryDescription
- );
-
- // creates the Declaration error and adds it in the errors list
- void declarationError(SourceLocation _sourceLocation, std::string const& _description);
- // creates the Declaration error and adds it in the errors list and throws FatalError
- void fatalDeclarationError(SourceLocation _sourceLocation, std::string const& _description);
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& m_scopes;
ASTNode const* m_currentScope = nullptr;
VariableScope* m_currentFunction = nullptr;
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
};
}
diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp
index e8da3ca4..fbc72e52 100644
--- a/libsolidity/analysis/PostTypeChecker.cpp
+++ b/libsolidity/analysis/PostTypeChecker.cpp
@@ -18,6 +18,7 @@
#include <libsolidity/analysis/PostTypeChecker.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/analysis/SemVerHandler.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/Version.h>
#include <boost/range/adaptor/map.hpp>
@@ -32,17 +33,7 @@ using namespace dev::solidity;
bool PostTypeChecker::check(ASTNode const& _astRoot)
{
_astRoot.accept(*this);
- return Error::containsOnlyWarnings(m_errors);
-}
-
-void PostTypeChecker::typeError(SourceLocation const& _location, std::string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::TypeError);
- *err <<
- errinfo_sourceLocation(_location) <<
- errinfo_comment(_description);
-
- m_errors.push_back(err);
+ return Error::containsOnlyWarnings(m_errorReporter.errors());
}
bool PostTypeChecker::visit(ContractDefinition const&)
@@ -57,7 +48,11 @@ void PostTypeChecker::endVisit(ContractDefinition const&)
solAssert(!m_currentConstVariable, "");
for (auto declaration: m_constVariables)
if (auto identifier = findCycle(declaration))
- typeError(declaration->location(), "The value of the constant " + declaration->name() + " has a cyclic dependency via " + identifier->name() + ".");
+ m_errorReporter.typeError(
+ declaration->location(),
+ "The value of the constant " + declaration->name() +
+ " has a cyclic dependency via " + identifier->name() + "."
+ );
m_constVariables.clear();
m_constVariableDependencies.clear();
diff --git a/libsolidity/analysis/PostTypeChecker.h b/libsolidity/analysis/PostTypeChecker.h
index 13751c16..dbdf50e0 100644
--- a/libsolidity/analysis/PostTypeChecker.h
+++ b/libsolidity/analysis/PostTypeChecker.h
@@ -28,6 +28,8 @@ namespace dev
namespace solidity
{
+class ErrorReporter;
+
/**
* This module performs analyses on the AST that are done after type checking and assignments of types:
* - whether there are circular references in constant state variables
@@ -37,7 +39,7 @@ class PostTypeChecker: private ASTConstVisitor
{
public:
/// @param _errors the reference to the list of errors and warnings to add them found during type checking.
- PostTypeChecker(ErrorList& _errors): m_errors(_errors) {}
+ PostTypeChecker(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {}
bool check(ASTNode const& _astRoot);
@@ -58,7 +60,7 @@ private:
std::set<VariableDeclaration const*> const& _seen = std::set<VariableDeclaration const*>{}
);
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
VariableDeclaration const* m_currentConstVariable = nullptr;
std::vector<VariableDeclaration const*> m_constVariables; ///< Required for determinism.
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index f5fffb57..b70b0f0e 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -28,6 +28,7 @@
#include <libsolidity/inlineasm/AsmAnalysis.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
#include <libsolidity/inlineasm/AsmData.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <boost/algorithm/string.hpp>
@@ -111,7 +112,7 @@ void ReferencesResolver::endVisit(FunctionTypeName const& _typeName)
case VariableDeclaration::Visibility::External:
break;
default:
- typeError(_typeName.location(), "Invalid visibility, can only be \"external\" or \"internal\".");
+ fatalTypeError(_typeName.location(), "Invalid visibility, can only be \"external\" or \"internal\".");
}
if (_typeName.isPayable() && _typeName.visibility() != VariableDeclaration::Visibility::External)
@@ -165,7 +166,8 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
// the type and size of external identifiers, which would result in false errors.
// The only purpose of this step is to fill the inline assembly annotation with
// external references.
- ErrorList errorsIgnored;
+ ErrorList errors;
+ ErrorReporter errorsIgnored(errors);
julia::ExternalIdentifierAccess::Resolver resolver =
[&](assembly::Identifier const& _identifier, julia::IdentifierContext) {
auto declarations = m_resolver.nameFromCurrentScope(_identifier.name);
@@ -303,29 +305,19 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
void ReferencesResolver::typeError(SourceLocation const& _location, string const& _description)
{
- auto err = make_shared<Error>(Error::Type::TypeError);
- *err << errinfo_sourceLocation(_location) << errinfo_comment(_description);
m_errorOccurred = true;
- m_errors.push_back(err);
+ m_errorReporter.typeError(_location, _description);
}
void ReferencesResolver::fatalTypeError(SourceLocation const& _location, string const& _description)
{
- typeError(_location, _description);
- BOOST_THROW_EXCEPTION(FatalError());
-}
-
-void ReferencesResolver::declarationError(SourceLocation const& _location, string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::DeclarationError);
- *err << errinfo_sourceLocation(_location) << errinfo_comment(_description);
m_errorOccurred = true;
- m_errors.push_back(err);
+ m_errorReporter.fatalTypeError(_location, _description);
}
void ReferencesResolver::fatalDeclarationError(SourceLocation const& _location, string const& _description)
{
- declarationError(_location, _description);
- BOOST_THROW_EXCEPTION(FatalError());
+ m_errorOccurred = true;
+ m_errorReporter.fatalDeclarationError(_location, _description);
}
diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h
index dce343d3..bbde19f9 100644
--- a/libsolidity/analysis/ReferencesResolver.h
+++ b/libsolidity/analysis/ReferencesResolver.h
@@ -33,6 +33,7 @@ namespace dev
namespace solidity
{
+class ErrorReporter;
class NameAndTypeResolver;
/**
@@ -43,11 +44,11 @@ class ReferencesResolver: private ASTConstVisitor
{
public:
ReferencesResolver(
- ErrorList& _errors,
+ ErrorReporter& _errorReporter,
NameAndTypeResolver& _resolver,
bool _resolveInsideCode = false
):
- m_errors(_errors),
+ m_errorReporter(_errorReporter),
m_resolver(_resolver),
m_resolveInsideCode(_resolveInsideCode)
{}
@@ -77,13 +78,10 @@ private:
/// Adds a new error to the list of errors and throws to abort type checking.
void fatalTypeError(SourceLocation const& _location, std::string const& _description);
- /// Adds a new error to the list of errors.
- void declarationError(const SourceLocation& _location, std::string const& _description);
-
/// Adds a new error to the list of errors and throws to abort type checking.
- void fatalDeclarationError(const SourceLocation& _location, std::string const& _description);
+ void fatalDeclarationError(SourceLocation const& _location, std::string const& _description);
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
NameAndTypeResolver& m_resolver;
/// Stack of return parameters.
std::vector<ParameterList const*> m_returnParameters;
diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp
index cfc863e0..375e9bde 100644
--- a/libsolidity/analysis/StaticAnalyzer.cpp
+++ b/libsolidity/analysis/StaticAnalyzer.cpp
@@ -22,6 +22,7 @@
#include <libsolidity/analysis/StaticAnalyzer.h>
#include <libsolidity/ast/AST.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <memory>
using namespace std;
@@ -31,7 +32,7 @@ using namespace dev::solidity;
bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit)
{
_sourceUnit.accept(*this);
- return Error::containsOnlyWarnings(m_errors);
+ return Error::containsOnlyWarnings(m_errorReporter.errors());
}
bool StaticAnalyzer::visit(ContractDefinition const& _contract)
@@ -62,7 +63,7 @@ void StaticAnalyzer::endVisit(FunctionDefinition const&)
m_nonPayablePublic = false;
for (auto const& var: m_localVarUseCount)
if (var.second == 0)
- warning(var.first->location(), "Unused local variable");
+ m_errorReporter.warning(var.first->location(), "Unused local variable");
m_localVarUseCount.clear();
}
@@ -104,7 +105,11 @@ bool StaticAnalyzer::visit(Return const& _return)
bool StaticAnalyzer::visit(ExpressionStatement const& _statement)
{
if (_statement.expression().annotation().isPure)
- warning(_statement.location(), "Statement has no effect.");
+ m_errorReporter.warning(
+ _statement.location(),
+ "Statement has no effect."
+ );
+
return true;
}
@@ -113,21 +118,14 @@ bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
if (m_nonPayablePublic && !m_library)
if (MagicType const* type = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type.get()))
if (type->kind() == MagicType::Kind::Message && _memberAccess.memberName() == "value")
- warning(_memberAccess.location(), "\"msg.value\" used in non-payable function. Do you want to add the \"payable\" modifier to this function?");
+ m_errorReporter.warning(
+ _memberAccess.location(),
+ "\"msg.value\" used in non-payable function. Do you want to add the \"payable\" modifier to this function?"
+ );
return true;
}
-void StaticAnalyzer::warning(SourceLocation const& _location, string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::Warning);
- *err <<
- errinfo_sourceLocation(_location) <<
- errinfo_comment(_description);
-
- m_errors.push_back(err);
-}
-
bool StaticAnalyzer::visit(InlineAssembly const& _inlineAssembly)
{
if (!m_currentFunction)
@@ -145,4 +143,3 @@ bool StaticAnalyzer::visit(InlineAssembly const& _inlineAssembly)
return true;
}
-
diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h
index 458bab2a..cd6913b5 100644
--- a/libsolidity/analysis/StaticAnalyzer.h
+++ b/libsolidity/analysis/StaticAnalyzer.h
@@ -44,15 +44,13 @@ class StaticAnalyzer: private ASTConstVisitor
{
public:
/// @param _errors the reference to the list of errors and warnings to add them found during static analysis.
- explicit StaticAnalyzer(ErrorList& _errors): m_errors(_errors) {}
+ explicit StaticAnalyzer(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {}
/// Performs static analysis on the given source unit and all of its sub-nodes.
/// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings
bool analyze(SourceUnit const& _sourceUnit);
private:
- /// Adds a new warning to the list of errors.
- void warning(SourceLocation const& _location, std::string const& _description);
virtual bool visit(ContractDefinition const& _contract) override;
virtual void endVisit(ContractDefinition const& _contract) override;
@@ -67,7 +65,7 @@ private:
virtual bool visit(MemberAccess const& _memberAccess) override;
virtual bool visit(InlineAssembly const& _inlineAssembly) override;
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
/// Flag that indicates whether the current contract definition is a library.
bool m_library = false;
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp
index 94e82a87..35d71d85 100644
--- a/libsolidity/analysis/SyntaxChecker.cpp
+++ b/libsolidity/analysis/SyntaxChecker.cpp
@@ -19,6 +19,7 @@
#include <memory>
#include <libsolidity/ast/AST.h>
#include <libsolidity/analysis/SemVerHandler.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/Version.h>
using namespace std;
@@ -29,27 +30,7 @@ using namespace dev::solidity;
bool SyntaxChecker::checkSyntax(ASTNode const& _astRoot)
{
_astRoot.accept(*this);
- return Error::containsOnlyWarnings(m_errors);
-}
-
-void SyntaxChecker::warning(SourceLocation const& _location, string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::Warning);
- *err <<
- errinfo_sourceLocation(_location) <<
- errinfo_comment(_description);
-
- m_errors.push_back(err);
-}
-
-void SyntaxChecker::syntaxError(SourceLocation const& _location, std::string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::SyntaxError);
- *err <<
- errinfo_sourceLocation(_location) <<
- errinfo_comment(_description);
-
- m_errors.push_back(err);
+ return Error::containsOnlyWarnings(m_errorReporter.errors());
}
bool SyntaxChecker::visit(SourceUnit const&)
@@ -74,11 +55,7 @@ void SyntaxChecker::endVisit(SourceUnit const& _sourceUnit)
to_string(recommendedVersion.patch());
string(";\"");
- auto err = make_shared<Error>(Error::Type::Warning);
- *err <<
- errinfo_sourceLocation(_sourceUnit.location()) <<
- errinfo_comment(errorString);
- m_errors.push_back(err);
+ m_errorReporter.warning(_sourceUnit.location(), errorString);
}
}
@@ -87,7 +64,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
solAssert(!_pragma.tokens().empty(), "");
solAssert(_pragma.tokens().size() == _pragma.literals().size(), "");
if (_pragma.tokens()[0] != Token::Identifier || _pragma.literals()[0] != "solidity")
- syntaxError(_pragma.location(), "Unknown pragma \"" + _pragma.literals()[0] + "\"");
+ m_errorReporter.syntaxError(_pragma.location(), "Unknown pragma \"" + _pragma.literals()[0] + "\"");
else
{
vector<Token::Value> tokens(_pragma.tokens().begin() + 1, _pragma.tokens().end());
@@ -96,7 +73,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
auto matchExpression = parser.parse();
SemVerVersion currentVersion{string(VersionString)};
if (!matchExpression.matches(currentVersion))
- syntaxError(
+ m_errorReporter.syntaxError(
_pragma.location(),
"Source file requires different compiler version (current compiler is " +
string(VersionString) + " - note that nightly builds are considered to be "
@@ -116,7 +93,7 @@ bool SyntaxChecker::visit(ModifierDefinition const&)
void SyntaxChecker::endVisit(ModifierDefinition const& _modifier)
{
if (!m_placeholderFound)
- syntaxError(_modifier.body().location(), "Modifier body does not contain '_'.");
+ m_errorReporter.syntaxError(_modifier.body().location(), "Modifier body does not contain '_'.");
m_placeholderFound = false;
}
@@ -146,7 +123,7 @@ bool SyntaxChecker::visit(Continue const& _continueStatement)
{
if (m_inLoopDepth <= 0)
// we're not in a for/while loop, report syntax error
- syntaxError(_continueStatement.location(), "\"continue\" has to be in a \"for\" or \"while\" loop.");
+ m_errorReporter.syntaxError(_continueStatement.location(), "\"continue\" has to be in a \"for\" or \"while\" loop.");
return true;
}
@@ -154,14 +131,14 @@ bool SyntaxChecker::visit(Break const& _breakStatement)
{
if (m_inLoopDepth <= 0)
// we're not in a for/while loop, report syntax error
- syntaxError(_breakStatement.location(), "\"break\" has to be in a \"for\" or \"while\" loop.");
+ m_errorReporter.syntaxError(_breakStatement.location(), "\"break\" has to be in a \"for\" or \"while\" loop.");
return true;
}
bool SyntaxChecker::visit(UnaryOperation const& _operation)
{
if (_operation.getOperator() == Token::Add)
- warning(_operation.location(), "Use of unary + is deprecated.");
+ m_errorReporter.warning(_operation.location(), "Use of unary + is deprecated.");
return true;
}
diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h
index 8d7dcdd3..b1857aa5 100644
--- a/libsolidity/analysis/SyntaxChecker.h
+++ b/libsolidity/analysis/SyntaxChecker.h
@@ -38,14 +38,11 @@ class SyntaxChecker: private ASTConstVisitor
{
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) {}
+ SyntaxChecker(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {}
bool checkSyntax(ASTNode const& _astRoot);
private:
- /// Adds a new error to the list of errors.
- void warning(SourceLocation const& _location, std::string const& _description);
- void syntaxError(SourceLocation const& _location, std::string const& _description);
virtual bool visit(SourceUnit const& _sourceUnit) override;
virtual void endVisit(SourceUnit const& _sourceUnit) override;
@@ -66,7 +63,7 @@ private:
virtual bool visit(PlaceholderStatement const& _placeholderStatement) override;
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
/// Flag that indicates whether a function modifier actually contains '_'.
bool m_placeholderFound = false;
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 528a23da..0fb0d212 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -27,6 +27,7 @@
#include <libsolidity/inlineasm/AsmAnalysis.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
#include <libsolidity/inlineasm/AsmData.h>
+#include <libsolidity/interface/ErrorReporter.h>
using namespace std;
using namespace dev;
@@ -43,10 +44,10 @@ bool TypeChecker::checkTypeRequirements(ASTNode const& _contract)
{
// We got a fatal error which required to stop further type checking, but we can
// continue normally from here.
- if (m_errors.empty())
+ if (m_errorReporter.errors().empty())
throw; // Something is weird here, rather throw again.
}
- return Error::containsOnlyWarnings(m_errors);
+ return Error::containsOnlyWarnings(m_errorReporter.errors());
}
TypePointer const& TypeChecker::type(Expression const& _expression) const
@@ -81,11 +82,11 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
if (function)
{
if (!function->returnParameters().empty())
- typeError(function->returnParameterList()->location(), "Non-empty \"returns\" directive for constructor.");
+ m_errorReporter.typeError(function->returnParameterList()->location(), "Non-empty \"returns\" directive for constructor.");
if (function->isDeclaredConst())
- typeError(function->location(), "Constructor cannot be defined as constant.");
+ m_errorReporter.typeError(function->location(), "Constructor cannot be defined as constant.");
if (function->visibility() != FunctionDefinition::Visibility::Public && function->visibility() != FunctionDefinition::Visibility::Internal)
- typeError(function->location(), "Constructor must be public or internal.");
+ m_errorReporter.typeError(function->location(), "Constructor must be public or internal.");
}
FunctionDefinition const* fallbackFunction = nullptr;
@@ -95,21 +96,19 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
{
if (fallbackFunction)
{
- auto err = make_shared<Error>(Error::Type::DeclarationError);
- *err << errinfo_comment("Only one fallback function is allowed.");
- m_errors.push_back(err);
+ m_errorReporter.declarationError(function->location(), "Only one fallback function is allowed.");
}
else
{
fallbackFunction = function;
if (_contract.isLibrary())
- typeError(fallbackFunction->location(), "Libraries cannot have fallback functions.");
+ m_errorReporter.typeError(fallbackFunction->location(), "Libraries cannot have fallback functions.");
if (fallbackFunction->isDeclaredConst())
- typeError(fallbackFunction->location(), "Fallback function cannot be declared constant.");
+ m_errorReporter.typeError(fallbackFunction->location(), "Fallback function cannot be declared constant.");
if (!fallbackFunction->parameters().empty())
- typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
+ m_errorReporter.typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
if (!fallbackFunction->returnParameters().empty())
- typeError(fallbackFunction->returnParameterList()->location(), "Fallback function cannot return values.");
+ m_errorReporter.typeError(fallbackFunction->returnParameterList()->location(), "Fallback function cannot return values.");
}
}
if (!function->isImplemented())
@@ -127,7 +126,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
{
FixedHash<4> const& hash = it.first;
if (hashes.count(hash))
- typeError(
+ m_errorReporter.typeError(
_contract.location(),
string("Function signature hash collision for ") + it.second->externalSignature()
);
@@ -156,12 +155,11 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
for (; it != functions[_contract.name()].end(); ++it)
ssl.append("Another declaration is here:", (*it)->location());
- auto err = make_shared<Error>(Error(Error::Type::DeclarationError));
- *err <<
- errinfo_sourceLocation(functions[_contract.name()].front()->location()) <<
- errinfo_comment("More than one constructor defined.") <<
- errinfo_secondarySourceLocation(ssl);
- m_errors.push_back(err);
+ m_errorReporter.declarationError(
+ functions[_contract.name()].front()->location(),
+ ssl,
+ "More than one constructor defined."
+ );
}
for (auto const& it: functions)
{
@@ -170,13 +168,14 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
for (size_t j = i + 1; j < overloads.size(); ++j)
if (FunctionType(*overloads[i]).hasEqualArgumentTypes(FunctionType(*overloads[j])))
{
- auto err = make_shared<Error>(Error(Error::Type::DeclarationError));
- *err <<
- errinfo_sourceLocation(overloads[j]->location()) <<
- errinfo_comment("Function with same name and arguments defined twice.") <<
- errinfo_secondarySourceLocation(SecondarySourceLocation().append(
- "Other declaration is here:", overloads[i]->location()));
- m_errors.push_back(err);
+ m_errorReporter.declarationError(
+ overloads[j]->location(),
+ SecondarySourceLocation().append(
+ "Other declaration is here:",
+ overloads[i]->location()
+ ),
+ "Function with same name and arguments defined twice."
+ );
}
}
}
@@ -213,7 +212,7 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont
else if (it->second)
{
if (!function->isImplemented())
- typeError(function->location(), "Redeclaring an already implemented function as abstract");
+ m_errorReporter.typeError(function->location(), "Redeclaring an already implemented function as abstract");
}
else if (function->isImplemented())
it->second = true;
@@ -285,7 +284,7 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr
continue; // constructors can neither be overridden nor override anything
string const& name = function->name();
if (modifiers.count(name))
- typeError(modifiers[name]->location(), "Override changes function to modifier.");
+ m_errorReporter.typeError(modifiers[name]->location(), "Override changes function to modifier.");
FunctionType functionType(*function);
// function should not change the return type
for (FunctionDefinition const* overriding: functions[name])
@@ -299,7 +298,7 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr
overriding->isPayable() != function->isPayable() ||
overridingType != functionType
)
- typeError(overriding->location(), "Override changes extended function signature.");
+ m_errorReporter.typeError(overriding->location(), "Override changes extended function signature.");
}
functions[name].push_back(function);
}
@@ -310,9 +309,9 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr
if (!override)
override = modifier;
else if (ModifierType(*override) != ModifierType(*modifier))
- typeError(override->location(), "Override changes modifier signature.");
+ m_errorReporter.typeError(override->location(), "Override changes modifier signature.");
if (!functions[name].empty())
- typeError(override->location(), "Override changes modifier to function.");
+ m_errorReporter.typeError(override->location(), "Override changes modifier to function.");
}
}
}
@@ -347,7 +346,7 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co
for (size_t i = 0; i < it.second.size(); ++i)
for (size_t j = i + 1; j < it.second.size(); ++j)
if (!it.second[i].second->hasEqualArgumentTypes(*it.second[j].second))
- typeError(
+ m_errorReporter.typeError(
it.second[j].first->location(),
"Function overload clash during conversion to external types for arguments."
);
@@ -357,11 +356,11 @@ void TypeChecker::checkLibraryRequirements(ContractDefinition const& _contract)
{
solAssert(_contract.isLibrary(), "");
if (!_contract.baseContracts().empty())
- typeError(_contract.location(), "Library is not allowed to inherit.");
+ m_errorReporter.typeError(_contract.location(), "Library is not allowed to inherit.");
for (auto const& var: _contract.stateVariables())
if (!var->isConstant())
- typeError(var->location(), "Library cannot have non-constant state variables");
+ m_errorReporter.typeError(var->location(), "Library cannot have non-constant state variables");
}
void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
@@ -370,16 +369,16 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
solAssert(base, "Base contract not available.");
if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
- typeError(_inheritance.location(), "Interfaces cannot inherit.");
+ m_errorReporter.typeError(_inheritance.location(), "Interfaces cannot inherit.");
if (base->isLibrary())
- typeError(_inheritance.location(), "Libraries cannot be inherited from.");
+ m_errorReporter.typeError(_inheritance.location(), "Libraries cannot be inherited from.");
auto const& arguments = _inheritance.arguments();
TypePointers parameterTypes = ContractType(*base).newExpressionType()->parameterTypes();
if (!arguments.empty() && parameterTypes.size() != arguments.size())
{
- typeError(
+ m_errorReporter.typeError(
_inheritance.location(),
"Wrong argument count for constructor call: " +
toString(arguments.size()) +
@@ -392,7 +391,7 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
for (size_t i = 0; i < arguments.size(); ++i)
if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i]))
- typeError(
+ m_errorReporter.typeError(
arguments[i]->location(),
"Invalid type for argument in constructor call. "
"Invalid implicit conversion from " +
@@ -409,17 +408,17 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
_usingFor.libraryName().annotation().referencedDeclaration
);
if (!library || !library->isLibrary())
- typeError(_usingFor.libraryName().location(), "Library name expected.");
+ m_errorReporter.typeError(_usingFor.libraryName().location(), "Library name expected.");
}
bool TypeChecker::visit(StructDefinition const& _struct)
{
if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
- typeError(_struct.location(), "Structs cannot be defined in interfaces.");
+ m_errorReporter.typeError(_struct.location(), "Structs cannot be defined in interfaces.");
for (ASTPointer<VariableDeclaration> const& member: _struct.members())
if (!type(*member)->canBeStored())
- typeError(member->location(), "Type cannot be used in struct.");
+ m_errorReporter.typeError(member->location(), "Type cannot be used in struct.");
// Check recursion, fatal error if detected.
using StructPointer = StructDefinition const*;
@@ -427,7 +426,7 @@ bool TypeChecker::visit(StructDefinition const& _struct)
function<void(StructPointer,StructPointersSet const&)> check = [&](StructPointer _struct, StructPointersSet const& _parents)
{
if (_parents.count(_struct))
- fatalTypeError(_struct->location(), "Recursive struct definition.");
+ m_errorReporter.fatalTypeError(_struct->location(), "Recursive struct definition.");
StructPointersSet parents = _parents;
parents.insert(_struct);
for (ASTPointer<VariableDeclaration> const& member: _struct->members())
@@ -452,18 +451,18 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
if (_function.isPayable())
{
if (isLibraryFunction)
- typeError(_function.location(), "Library functions cannot be payable.");
+ m_errorReporter.typeError(_function.location(), "Library functions cannot be payable.");
if (!_function.isConstructor() && !_function.name().empty() && !_function.isPartOfExternalInterface())
- typeError(_function.location(), "Internal functions cannot be payable.");
+ m_errorReporter.typeError(_function.location(), "Internal functions cannot be payable.");
if (_function.isDeclaredConst())
- typeError(_function.location(), "Functions cannot be constant and payable at the same time.");
+ m_errorReporter.typeError(_function.location(), "Functions cannot be constant and payable at the same time.");
}
for (ASTPointer<VariableDeclaration> const& var: _function.parameters() + _function.returnParameters())
{
if (!type(*var)->canLiveOutsideStorage())
- typeError(var->location(), "Type is required to live outside storage.");
+ m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
if (_function.visibility() >= FunctionDefinition::Visibility::Public && !(type(*var)->interfaceType(isLibraryFunction)))
- fatalTypeError(var->location(), "Internal type is not allowed for public or external functions.");
+ m_errorReporter.fatalTypeError(var->location(), "Internal type is not allowed for public or external functions.");
}
for (ASTPointer<ModifierInvocation> const& modifier: _function.modifiers())
visitManually(
@@ -475,11 +474,11 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
{
if (_function.isImplemented())
- typeError(_function.location(), "Functions in interfaces cannot have an implementation.");
+ m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot have an implementation.");
if (_function.visibility() < FunctionDefinition::Visibility::Public)
- typeError(_function.location(), "Functions in interfaces cannot be internal or private.");
+ m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot be internal or private.");
if (_function.isConstructor())
- typeError(_function.location(), "Constructor cannot be defined in interfaces.");
+ m_errorReporter.typeError(_function.location(), "Constructor cannot be defined in interfaces.");
}
if (_function.isImplemented())
_function.body().accept(*this);
@@ -489,7 +488,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
bool TypeChecker::visit(VariableDeclaration const& _variable)
{
if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
- typeError(_variable.location(), "Variables cannot be declared in interfaces.");
+ m_errorReporter.typeError(_variable.location(), "Variables cannot be declared in interfaces.");
// Variables can be declared without type (with "var"), in which case the first assignment
// sets the type.
@@ -505,19 +504,19 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
if (_variable.isConstant())
{
if (!_variable.isStateVariable())
- typeError(_variable.location(), "Illegal use of \"constant\" specifier.");
+ m_errorReporter.typeError(_variable.location(), "Illegal use of \"constant\" specifier.");
if (!_variable.type()->isValueType())
{
bool allowed = false;
if (auto arrayType = dynamic_cast<ArrayType const*>(_variable.type().get()))
allowed = arrayType->isString();
if (!allowed)
- typeError(_variable.location(), "Constants of non-value type not yet implemented.");
+ m_errorReporter.typeError(_variable.location(), "Constants of non-value type not yet implemented.");
}
if (!_variable.value())
- typeError(_variable.location(), "Uninitialized \"constant\" variable.");
+ m_errorReporter.typeError(_variable.location(), "Uninitialized \"constant\" variable.");
else if (!_variable.value()->annotation().isPure)
- warning(
+ m_errorReporter.warning(
_variable.value()->location(),
"Initial value for constant variable has to be compile-time constant. "
"This will fail to compile with the next breaking version change."
@@ -527,20 +526,20 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
{
if (varType->dataStoredIn(DataLocation::Memory) || varType->dataStoredIn(DataLocation::CallData))
if (!varType->canLiveOutsideStorage())
- typeError(_variable.location(), "Type " + varType->toString() + " is only valid in storage.");
+ m_errorReporter.typeError(_variable.location(), "Type " + varType->toString() + " is only valid in storage.");
}
else if (
_variable.visibility() >= VariableDeclaration::Visibility::Public &&
!FunctionType(_variable).interfaceFunctionType()
)
- typeError(_variable.location(), "Internal type is not allowed for public state variables.");
+ m_errorReporter.typeError(_variable.location(), "Internal type is not allowed for public state variables.");
return false;
}
bool TypeChecker::visit(EnumDefinition const& _enum)
{
if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
- typeError(_enum.location(), "Enumerable cannot be declared in interfaces.");
+ m_errorReporter.typeError(_enum.location(), "Enumerable cannot be declared in interfaces.");
return false;
}
@@ -572,12 +571,12 @@ void TypeChecker::visitManually(
}
if (!parameters)
{
- typeError(_modifier.location(), "Referenced declaration is neither modifier nor base class.");
+ m_errorReporter.typeError(_modifier.location(), "Referenced declaration is neither modifier nor base class.");
return;
}
if (parameters->size() != arguments.size())
{
- typeError(
+ m_errorReporter.typeError(
_modifier.location(),
"Wrong argument count for modifier invocation: " +
toString(arguments.size()) +
@@ -589,7 +588,7 @@ void TypeChecker::visitManually(
}
for (size_t i = 0; i < _modifier.arguments().size(); ++i)
if (!type(*arguments[i])->isImplicitlyConvertibleTo(*type(*(*parameters)[i])))
- typeError(
+ m_errorReporter.typeError(
arguments[i]->location(),
"Invalid type for argument in modifier invocation. "
"Invalid implicit conversion from " +
@@ -608,13 +607,13 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
if (var->isIndexed())
numIndexed++;
if (_eventDef.isAnonymous() && numIndexed > 4)
- typeError(_eventDef.location(), "More than 4 indexed arguments for anonymous event.");
+ m_errorReporter.typeError(_eventDef.location(), "More than 4 indexed arguments for anonymous event.");
else if (!_eventDef.isAnonymous() && numIndexed > 3)
- typeError(_eventDef.location(), "More than 3 indexed arguments for event.");
+ m_errorReporter.typeError(_eventDef.location(), "More than 3 indexed arguments for event.");
if (!type(*var)->canLiveOutsideStorage())
- typeError(var->location(), "Type is required to live outside storage.");
+ m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
if (!type(*var)->interfaceType(false))
- typeError(var->location(), "Internal type is not allowed as event parameter type.");
+ m_errorReporter.typeError(var->location(), "Internal type is not allowed as event parameter type.");
}
return false;
}
@@ -624,7 +623,7 @@ void TypeChecker::endVisit(FunctionTypeName const& _funType)
FunctionType const& fun = dynamic_cast<FunctionType const&>(*_funType.annotation().type);
if (fun.kind() == FunctionType::Kind::External)
if (!fun.canBeUsedExternally(false))
- typeError(_funType.location(), "External function type uses internal types.");
+ m_errorReporter.typeError(_funType.location(), "External function type uses internal types.");
}
bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
@@ -647,39 +646,39 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
if (!var->isStateVariable() && !var->type()->dataStoredIn(DataLocation::Storage))
{
- typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
+ m_errorReporter.typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
return size_t(-1);
}
else if (_context != julia::IdentifierContext::RValue)
{
- typeError(_identifier.location, "Storage variables cannot be assigned to.");
+ m_errorReporter.typeError(_identifier.location, "Storage variables cannot be assigned to.");
return size_t(-1);
}
}
else if (var->isConstant())
{
- typeError(_identifier.location, "Constant variables not supported by inline assembly.");
+ m_errorReporter.typeError(_identifier.location, "Constant variables not supported by inline assembly.");
return size_t(-1);
}
else if (!var->isLocalVariable())
{
- typeError(_identifier.location, "Only local variables are supported. To access storage variables, use the _slot and _offset suffixes.");
+ m_errorReporter.typeError(_identifier.location, "Only local variables are supported. To access storage variables, use the _slot and _offset suffixes.");
return size_t(-1);
}
else if (var->type()->dataStoredIn(DataLocation::Storage))
{
- typeError(_identifier.location, "You have to use the _slot or _offset prefix to access storage reference variables.");
+ m_errorReporter.typeError(_identifier.location, "You have to use the _slot or _offset prefix to access storage reference variables.");
return size_t(-1);
}
else if (var->type()->sizeOnStack() != 1)
{
- typeError(_identifier.location, "Only types that use one stack slot are supported.");
+ m_errorReporter.typeError(_identifier.location, "Only types that use one stack slot are supported.");
return size_t(-1);
}
}
else if (_context == julia::IdentifierContext::LValue)
{
- typeError(_identifier.location, "Only local variables can be assigned to in inline assembly.");
+ m_errorReporter.typeError(_identifier.location, "Only local variables can be assigned to in inline assembly.");
return size_t(-1);
}
@@ -696,7 +695,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
if (!contract->isLibrary())
{
- typeError(_identifier.location, "Expected a library.");
+ m_errorReporter.typeError(_identifier.location, "Expected a library.");
return size_t(-1);
}
}
@@ -710,7 +709,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
_inlineAssembly.annotation().analysisInfo = make_shared<assembly::AsmAnalysisInfo>();
assembly::AsmAnalyzer analyzer(
*_inlineAssembly.annotation().analysisInfo,
- m_errors,
+ m_errorReporter,
false,
identifierAccess
);
@@ -754,7 +753,7 @@ void TypeChecker::endVisit(Return const& _return)
ParameterList const* params = _return.annotation().functionReturnParameters;
if (!params)
{
- typeError(_return.location(), "Return arguments not allowed.");
+ m_errorReporter.typeError(_return.location(), "Return arguments not allowed.");
return;
}
TypePointers returnTypes;
@@ -763,9 +762,9 @@ void TypeChecker::endVisit(Return const& _return)
if (auto tupleType = dynamic_cast<TupleType const*>(type(*_return.expression()).get()))
{
if (tupleType->components().size() != params->parameters().size())
- typeError(_return.location(), "Different number of arguments in return statement than in returns declaration.");
+ m_errorReporter.typeError(_return.location(), "Different number of arguments in return statement than in returns declaration.");
else if (!tupleType->isImplicitlyConvertibleTo(TupleType(returnTypes)))
- typeError(
+ m_errorReporter.typeError(
_return.expression()->location(),
"Return argument type " +
type(*_return.expression())->toString() +
@@ -775,12 +774,12 @@ void TypeChecker::endVisit(Return const& _return)
);
}
else if (params->parameters().size() != 1)
- typeError(_return.location(), "Different number of arguments in return statement than in returns declaration.");
+ m_errorReporter.typeError(_return.location(), "Different number of arguments in return statement than in returns declaration.");
else
{
TypePointer const& expected = type(*params->parameters().front());
if (!type(*_return.expression())->isImplicitlyConvertibleTo(*expected))
- typeError(
+ m_errorReporter.typeError(
_return.expression()->location(),
"Return argument type " +
type(*_return.expression())->toString() +
@@ -797,20 +796,20 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
{
// No initial value is only permitted for single variables with specified type.
if (_statement.declarations().size() != 1 || !_statement.declarations().front())
- fatalTypeError(_statement.location(), "Assignment necessary for type detection.");
+ m_errorReporter.fatalTypeError(_statement.location(), "Assignment necessary for type detection.");
VariableDeclaration const& varDecl = *_statement.declarations().front();
if (!varDecl.annotation().type)
- fatalTypeError(_statement.location(), "Assignment necessary for type detection.");
+ m_errorReporter.fatalTypeError(_statement.location(), "Assignment necessary for type detection.");
if (auto ref = dynamic_cast<ReferenceType const*>(type(varDecl).get()))
{
if (ref->dataStoredIn(DataLocation::Storage))
- warning(
+ m_errorReporter.warning(
varDecl.location(),
"Uninitialized storage pointer. Did you mean '<type> memory " + varDecl.name() + "'?"
);
}
else if (dynamic_cast<MappingType const*>(type(varDecl).get()))
- typeError(
+ m_errorReporter.typeError(
varDecl.location(),
"Uninitialized mapping. Mappings cannot be created dynamically, you have to assign them from a state variable."
);
@@ -836,7 +835,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
if (variables.empty())
{
if (!valueTypes.empty())
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_statement.location(),
"Too many components (" +
toString(valueTypes.size()) +
@@ -844,7 +843,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
);
}
else if (valueTypes.size() != variables.size() && !variables.front() && !variables.back())
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_statement.location(),
"Wildcard both at beginning and end of variable declaration list is only allowed "
"if the number of components is equal."
@@ -853,7 +852,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
if (!variables.empty() && (!variables.back() || !variables.front()))
--minNumValues;
if (valueTypes.size() < minNumValues)
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_statement.location(),
"Not enough components (" +
toString(valueTypes.size()) +
@@ -861,7 +860,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
toString(minNumValues) + ")."
);
if (valueTypes.size() > variables.size() && variables.front() && variables.back())
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_statement.location(),
"Too many components (" +
toString(valueTypes.size()) +
@@ -892,7 +891,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
if (!var.annotation().type)
{
if (valueComponentType->category() == Type::Category::RationalNumber)
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_statement.initialValue()->location(),
"Invalid rational " +
valueComponentType->toString() +
@@ -902,7 +901,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
solAssert(false, "");
}
else if (*var.annotation().type == TupleType())
- typeError(
+ m_errorReporter.typeError(
var.location(),
"Cannot declare variable with void (empty tuple) type."
);
@@ -918,7 +917,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
dynamic_cast<RationalNumberType const&>(*valueComponentType).isFractional() &&
valueComponentType->mobileType()
)
- typeError(
+ m_errorReporter.typeError(
_statement.location(),
"Type " +
valueComponentType->toString() +
@@ -929,7 +928,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
" or use an explicit conversion."
);
else
- typeError(
+ m_errorReporter.typeError(
_statement.location(),
"Type " +
valueComponentType->toString() +
@@ -947,7 +946,7 @@ void TypeChecker::endVisit(ExpressionStatement const& _statement)
{
if (type(_statement.expression())->category() == Type::Category::RationalNumber)
if (!dynamic_cast<RationalNumberType const&>(*type(_statement.expression())).mobileType())
- typeError(_statement.expression().location(), "Invalid rational number.");
+ m_errorReporter.typeError(_statement.expression().location(), "Invalid rational number.");
if (auto call = dynamic_cast<FunctionCall const*>(&_statement.expression()))
{
@@ -959,9 +958,9 @@ void TypeChecker::endVisit(ExpressionStatement const& _statement)
kind == FunctionType::Kind::BareCallCode ||
kind == FunctionType::Kind::BareDelegateCall
)
- warning(_statement.location(), "Return value of low-level calls not used.");
+ m_errorReporter.warning(_statement.location(), "Return value of low-level calls not used.");
else if (kind == FunctionType::Kind::Send)
- warning(_statement.location(), "Failure condition of 'send' ignored. Consider using 'transfer' instead.");
+ m_errorReporter.warning(_statement.location(), "Failure condition of 'send' ignored. Consider using 'transfer' instead.");
}
}
}
@@ -976,14 +975,14 @@ bool TypeChecker::visit(Conditional const& _conditional)
TypePointer trueType = type(_conditional.trueExpression())->mobileType();
TypePointer falseType = type(_conditional.falseExpression())->mobileType();
if (!trueType)
- fatalTypeError(_conditional.trueExpression().location(), "Invalid mobile type.");
+ m_errorReporter.fatalTypeError(_conditional.trueExpression().location(), "Invalid mobile type.");
if (!falseType)
- fatalTypeError(_conditional.falseExpression().location(), "Invalid mobile type.");
+ m_errorReporter.fatalTypeError(_conditional.falseExpression().location(), "Invalid mobile type.");
TypePointer commonType = Type::commonType(trueType, falseType);
if (!commonType)
{
- typeError(
+ m_errorReporter.typeError(
_conditional.location(),
"True expression's type " +
trueType->toString() +
@@ -1003,7 +1002,7 @@ bool TypeChecker::visit(Conditional const& _conditional)
_conditional.falseExpression().annotation().isPure;
if (_conditional.annotation().lValueRequested)
- typeError(
+ m_errorReporter.typeError(
_conditional.location(),
"Conditional expression as left value is not supported yet."
);
@@ -1019,7 +1018,7 @@ bool TypeChecker::visit(Assignment const& _assignment)
if (TupleType const* tupleType = dynamic_cast<TupleType const*>(t.get()))
{
if (_assignment.assignmentOperator() != Token::Assign)
- typeError(
+ m_errorReporter.typeError(
_assignment.location(),
"Compound assignment is not allowed for tuple types."
);
@@ -1029,7 +1028,7 @@ bool TypeChecker::visit(Assignment const& _assignment)
}
else if (t->category() == Type::Category::Mapping)
{
- typeError(_assignment.location(), "Mappings cannot be assigned to.");
+ m_errorReporter.typeError(_assignment.location(), "Mappings cannot be assigned to.");
_assignment.rightHandSide().accept(*this);
}
else if (_assignment.assignmentOperator() == Token::Assign)
@@ -1043,7 +1042,7 @@ bool TypeChecker::visit(Assignment const& _assignment)
type(_assignment.rightHandSide())
);
if (!resultType || *resultType != *t)
- typeError(
+ m_errorReporter.typeError(
_assignment.location(),
"Operator " +
string(Token::toString(_assignment.assignmentOperator())) +
@@ -1064,7 +1063,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
if (_tuple.annotation().lValueRequested)
{
if (_tuple.isInlineArray())
- fatalTypeError(_tuple.location(), "Inline array type cannot be declared as LValue.");
+ m_errorReporter.fatalTypeError(_tuple.location(), "Inline array type cannot be declared as LValue.");
for (auto const& component: components)
if (component)
{
@@ -1088,7 +1087,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
{
// Outside of an lvalue-context, the only situation where a component can be empty is (x,).
if (!components[i] && !(i == 1 && components.size() == 2))
- fatalTypeError(_tuple.location(), "Tuple component cannot be empty.");
+ m_errorReporter.fatalTypeError(_tuple.location(), "Tuple component cannot be empty.");
else if (components[i])
{
components[i]->accept(*this);
@@ -1098,7 +1097,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
if (_tuple.isInlineArray())
{
if ((i == 0 || inlineArrayType) && !types[i]->mobileType())
- fatalTypeError(components[i]->location(), "Invalid mobile type.");
+ m_errorReporter.fatalTypeError(components[i]->location(), "Invalid mobile type.");
if (i == 0)
inlineArrayType = types[i]->mobileType();
@@ -1115,7 +1114,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
if (_tuple.isInlineArray())
{
if (!inlineArrayType)
- fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements.");
+ m_errorReporter.fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements.");
_tuple.annotation().type = make_shared<ArrayType>(DataLocation::Memory, inlineArrayType, types.size());
}
else
@@ -1147,7 +1146,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
TypePointer t = type(_operation.subExpression())->unaryOperatorResult(op);
if (!t)
{
- typeError(
+ m_errorReporter.typeError(
_operation.location(),
"Unary operator " +
string(Token::toString(op)) +
@@ -1168,7 +1167,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
TypePointer commonType = leftType->binaryOperatorResult(_operation.getOperator(), rightType);
if (!commonType)
{
- typeError(
+ m_errorReporter.typeError(
_operation.location(),
"Operator " +
string(Token::toString(_operation.getOperator())) +
@@ -1201,7 +1200,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
commonType->category() == Type::Category::FixedPoint &&
dynamic_cast<FixedPointType const&>(*commonType).numBits() != 256
))
- warning(
+ m_errorReporter.warning(
_operation.location(),
"Result of exponentiation has type " + commonType->toString() + " and thus "
"might overflow. Silence this warning by converting the literal to the "
@@ -1254,9 +1253,9 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
TypeType const& t = dynamic_cast<TypeType const&>(*expressionType);
TypePointer resultType = t.actualType();
if (arguments.size() != 1)
- typeError(_functionCall.location(), "Exactly one argument expected for explicit type conversion.");
+ m_errorReporter.typeError(_functionCall.location(), "Exactly one argument expected for explicit type conversion.");
else if (!isPositionalCall)
- typeError(_functionCall.location(), "Type conversion cannot allow named arguments.");
+ m_errorReporter.typeError(_functionCall.location(), "Type conversion cannot allow named arguments.");
else
{
TypePointer const& argType = type(*arguments.front());
@@ -1265,7 +1264,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
// (data location cannot yet be specified for type conversions)
resultType = ReferenceType::copyForLocationIfReference(argRefType->location(), resultType);
if (!argType->isExplicitlyConvertibleTo(*resultType))
- typeError(_functionCall.location(), "Explicit type conversion not allowed.");
+ m_errorReporter.typeError(_functionCall.location(), "Explicit type conversion not allowed.");
}
_functionCall.annotation().type = resultType;
_functionCall.annotation().isPure = isPure;
@@ -1298,7 +1297,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
if (!functionType)
{
- typeError(_functionCall.location(), "Type is not callable");
+ m_errorReporter.typeError(_functionCall.location(), "Type is not callable");
_functionCall.annotation().type = make_shared<TupleType>();
return false;
}
@@ -1323,7 +1322,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
for (auto const& member: membersRemovedForStructConstructor)
msg += " " + member;
}
- typeError(_functionCall.location(), msg);
+ m_errorReporter.typeError(_functionCall.location(), msg);
}
else if (isPositionalCall)
{
@@ -1335,10 +1334,10 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
{
if (auto t = dynamic_cast<RationalNumberType const*>(argType.get()))
if (!t->mobileType())
- typeError(arguments[i]->location(), "Invalid rational number (too large or division by zero).");
+ m_errorReporter.typeError(arguments[i]->location(), "Invalid rational number (too large or division by zero).");
}
else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i]))
- typeError(
+ m_errorReporter.typeError(
arguments[i]->location(),
"Invalid type for argument in function call. "
"Invalid implicit conversion from " +
@@ -1354,14 +1353,14 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
// call by named arguments
auto const& parameterNames = functionType->parameterNames();
if (functionType->takesArbitraryParameters())
- typeError(
+ m_errorReporter.typeError(
_functionCall.location(),
"Named arguments cannnot be used for functions that take arbitrary parameters."
);
else if (parameterNames.size() > argumentNames.size())
- typeError(_functionCall.location(), "Some argument names are missing.");
+ m_errorReporter.typeError(_functionCall.location(), "Some argument names are missing.");
else if (parameterNames.size() < argumentNames.size())
- typeError(_functionCall.location(), "Too many arguments.");
+ m_errorReporter.typeError(_functionCall.location(), "Too many arguments.");
else
{
// check duplicate names
@@ -1371,7 +1370,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
if (*argumentNames[i] == *argumentNames[j])
{
duplication = true;
- typeError(arguments[i]->location(), "Duplicate named argument.");
+ m_errorReporter.typeError(arguments[i]->location(), "Duplicate named argument.");
}
// check actual types
@@ -1385,7 +1384,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
found = true;
// check type convertible
if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[j]))
- typeError(
+ m_errorReporter.typeError(
arguments[i]->location(),
"Invalid type for argument in function call. "
"Invalid implicit conversion from " +
@@ -1398,7 +1397,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
}
if (!found)
- typeError(
+ m_errorReporter.typeError(
_functionCall.location(),
"Named argument does not match function declaration."
);
@@ -1419,11 +1418,11 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
auto contract = dynamic_cast<ContractDefinition const*>(&dereference(*contractName));
if (!contract)
- fatalTypeError(_newExpression.location(), "Identifier is not a contract.");
+ m_errorReporter.fatalTypeError(_newExpression.location(), "Identifier is not a contract.");
if (!contract->annotation().isFullyImplemented)
- typeError(_newExpression.location(), "Trying to create an instance of an abstract contract.");
+ m_errorReporter.typeError(_newExpression.location(), "Trying to create an instance of an abstract contract.");
if (!contract->constructorIsPublic())
- typeError(_newExpression.location(), "Contract with internal constructor cannot be created directly.");
+ m_errorReporter.typeError(_newExpression.location(), "Contract with internal constructor cannot be created directly.");
solAssert(!!m_scope, "");
m_scope->annotation().contractDependencies.insert(contract);
@@ -1432,7 +1431,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
"Linearized base contracts not yet available."
);
if (contractDependenciesAreCyclic(*m_scope))
- typeError(
+ m_errorReporter.typeError(
_newExpression.location(),
"Circular reference for contract creation (cannot create instance of derived or same contract)."
);
@@ -1442,12 +1441,12 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
else if (type->category() == Type::Category::Array)
{
if (!type->canLiveOutsideStorage())
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_newExpression.typeName().location(),
"Type cannot live outside storage."
);
if (!type->isDynamicallySized())
- typeError(
+ m_errorReporter.typeError(
_newExpression.typeName().location(),
"Length has to be placed in parentheses after the array type for new expression."
);
@@ -1462,7 +1461,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
_newExpression.annotation().isPure = true;
}
else
- fatalTypeError(_newExpression.location(), "Contract or array type expected.");
+ m_errorReporter.fatalTypeError(_newExpression.location(), "Contract or array type expected.");
}
bool TypeChecker::visit(MemberAccess const& _memberAccess)
@@ -1493,13 +1492,13 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
exprType
);
if (!storageType->members(m_scope).membersByName(memberName).empty())
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_memberAccess.location(),
"Member \"" + memberName + "\" is not available in " +
exprType->toString() +
" outside of storage."
);
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_memberAccess.location(),
"Member \"" + memberName + "\" not found or not visible "
"after argument-dependent lookup in " + exprType->toString() +
@@ -1507,7 +1506,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
);
}
else if (possibleMembers.size() > 1)
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_memberAccess.location(),
"Member \"" + memberName + "\" not unique "
"after argument-dependent lookup in " + exprType->toString() +
@@ -1520,7 +1519,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
if (auto funType = dynamic_cast<FunctionType const*>(annotation.type.get()))
if (funType->bound() && !exprType->isImplicitlyConvertibleTo(*funType->selfType()))
- typeError(
+ m_errorReporter.typeError(
_memberAccess.location(),
"Function \"" + memberName + "\" cannot be called on an object of type " +
exprType->toString() + " (expected " + funType->selfType()->toString() + ")"
@@ -1568,10 +1567,10 @@ bool TypeChecker::visit(IndexAccess const& _access)
{
ArrayType const& actualType = dynamic_cast<ArrayType const&>(*baseType);
if (!index)
- typeError(_access.location(), "Index expression cannot be omitted.");
+ m_errorReporter.typeError(_access.location(), "Index expression cannot be omitted.");
else if (actualType.isString())
{
- typeError(_access.location(), "Index access for string is not possible.");
+ m_errorReporter.typeError(_access.location(), "Index access for string is not possible.");
index->accept(*this);
}
else
@@ -1581,7 +1580,7 @@ bool TypeChecker::visit(IndexAccess const& _access)
{
if (!numberType->isFractional()) // error is reported above
if (!actualType.isDynamicallySized() && actualType.length() <= numberType->literalValue(nullptr))
- typeError(_access.location(), "Out of bounds array access.");
+ m_errorReporter.typeError(_access.location(), "Out of bounds array access.");
}
}
resultType = actualType.baseType();
@@ -1592,7 +1591,7 @@ bool TypeChecker::visit(IndexAccess const& _access)
{
MappingType const& actualType = dynamic_cast<MappingType const&>(*baseType);
if (!index)
- typeError(_access.location(), "Index expression cannot be omitted.");
+ m_errorReporter.typeError(_access.location(), "Index expression cannot be omitted.");
else
expectType(*index, *actualType.keyType());
resultType = actualType.valueType();
@@ -1614,7 +1613,7 @@ bool TypeChecker::visit(IndexAccess const& _access)
length->literalValue(nullptr)
));
else
- fatalTypeError(index->location(), "Integer constant expected.");
+ m_errorReporter.fatalTypeError(index->location(), "Integer constant expected.");
}
break;
}
@@ -1622,20 +1621,20 @@ bool TypeChecker::visit(IndexAccess const& _access)
{
FixedBytesType const& bytesType = dynamic_cast<FixedBytesType const&>(*baseType);
if (!index)
- typeError(_access.location(), "Index expression cannot be omitted.");
+ m_errorReporter.typeError(_access.location(), "Index expression cannot be omitted.");
else
{
expectType(*index, IntegerType(256));
if (auto integerType = dynamic_cast<RationalNumberType const*>(type(*index).get()))
if (bytesType.numBytes() <= integerType->literalValue(nullptr))
- typeError(_access.location(), "Out of bounds array access.");
+ m_errorReporter.typeError(_access.location(), "Out of bounds array access.");
}
resultType = make_shared<FixedBytesType>(1);
isLValue = false; // @todo this heavily depends on how it is embedded
break;
}
default:
- fatalTypeError(
+ m_errorReporter.fatalTypeError(
_access.baseExpression().location(),
"Indexed expression has to be a type, mapping or array (is " + baseType->toString() + ")"
);
@@ -1665,14 +1664,14 @@ bool TypeChecker::visit(Identifier const& _identifier)
candidates.push_back(declaration);
}
if (candidates.empty())
- fatalTypeError(_identifier.location(), "No matching declaration found after variable lookup.");
+ m_errorReporter.fatalTypeError(_identifier.location(), "No matching declaration found after variable lookup.");
else if (candidates.size() == 1)
annotation.referencedDeclaration = candidates.front();
else
- fatalTypeError(_identifier.location(), "No unique declaration found after variable lookup.");
+ m_errorReporter.fatalTypeError(_identifier.location(), "No unique declaration found after variable lookup.");
}
else if (annotation.overloadedDeclarations.empty())
- fatalTypeError(_identifier.location(), "No candidates for overload resolution found.");
+ m_errorReporter.fatalTypeError(_identifier.location(), "No candidates for overload resolution found.");
else if (annotation.overloadedDeclarations.size() == 1)
annotation.referencedDeclaration = *annotation.overloadedDeclarations.begin();
else
@@ -1688,11 +1687,11 @@ bool TypeChecker::visit(Identifier const& _identifier)
candidates.push_back(declaration);
}
if (candidates.empty())
- fatalTypeError(_identifier.location(), "No matching declaration found after argument-dependent lookup.");
+ m_errorReporter.fatalTypeError(_identifier.location(), "No matching declaration found after argument-dependent lookup.");
else if (candidates.size() == 1)
annotation.referencedDeclaration = candidates.front();
else
- fatalTypeError(_identifier.location(), "No unique declaration found after argument-dependent lookup.");
+ m_errorReporter.fatalTypeError(_identifier.location(), "No unique declaration found after argument-dependent lookup.");
}
}
solAssert(
@@ -1702,7 +1701,7 @@ bool TypeChecker::visit(Identifier const& _identifier)
annotation.isLValue = annotation.referencedDeclaration->isLValue();
annotation.type = annotation.referencedDeclaration->type();
if (!annotation.type)
- fatalTypeError(_identifier.location(), "Declaration referenced before type could be determined.");
+ m_errorReporter.fatalTypeError(_identifier.location(), "Declaration referenced before type could be determined.");
if (auto variableDeclaration = dynamic_cast<VariableDeclaration const*>(annotation.referencedDeclaration))
annotation.isPure = annotation.isConstant = variableDeclaration->isConstant();
else if (dynamic_cast<MagicVariableDeclaration const*>(annotation.referencedDeclaration))
@@ -1727,7 +1726,7 @@ void TypeChecker::endVisit(Literal const& _literal)
return;
}
else
- warning(
+ m_errorReporter.warning(
_literal.location(),
"This looks like an address but has an invalid checksum. "
"If this is not used as an address, please prepend '00'."
@@ -1736,7 +1735,7 @@ void TypeChecker::endVisit(Literal const& _literal)
_literal.annotation().type = Type::forLiteral(_literal);
_literal.annotation().isPure = true;
if (!_literal.annotation().type)
- fatalTypeError(_literal.location(), "Invalid literal value.");
+ m_errorReporter.fatalTypeError(_literal.location(), "Invalid literal value.");
}
bool TypeChecker::contractDependenciesAreCyclic(
@@ -1777,7 +1776,7 @@ void TypeChecker::expectType(Expression const& _expression, Type const& _expecte
dynamic_pointer_cast<RationalNumberType const>(type(_expression))->isFractional() &&
type(_expression)->mobileType()
)
- typeError(
+ m_errorReporter.typeError(
_expression.location(),
"Type " +
type(_expression)->toString() +
@@ -1788,7 +1787,7 @@ void TypeChecker::expectType(Expression const& _expression, Type const& _expecte
" or use an explicit conversion."
);
else
- typeError(
+ m_errorReporter.typeError(
_expression.location(),
"Type " +
type(_expression)->toString() +
@@ -1805,33 +1804,8 @@ void TypeChecker::requireLValue(Expression const& _expression)
_expression.accept(*this);
if (_expression.annotation().isConstant)
- typeError(_expression.location(), "Cannot assign to a constant variable.");
+ m_errorReporter.typeError(_expression.location(), "Cannot assign to a constant variable.");
else if (!_expression.annotation().isLValue)
- typeError(_expression.location(), "Expression has to be an lvalue.");
-}
-
-void TypeChecker::typeError(SourceLocation const& _location, string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::TypeError);
- *err <<
- errinfo_sourceLocation(_location) <<
- errinfo_comment(_description);
-
- m_errors.push_back(err);
+ m_errorReporter.typeError(_expression.location(), "Expression has to be an lvalue.");
}
-void TypeChecker::warning(SourceLocation const& _location, string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::Warning);
- *err <<
- errinfo_sourceLocation(_location) <<
- errinfo_comment(_description);
-
- m_errors.push_back(err);
-}
-
-void TypeChecker::fatalTypeError(SourceLocation const& _location, string const& _description)
-{
- typeError(_location, _description);
- BOOST_THROW_EXCEPTION(FatalError());
-}
diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h
index 88559f44..2fa66f97 100644
--- a/libsolidity/analysis/TypeChecker.h
+++ b/libsolidity/analysis/TypeChecker.h
@@ -22,7 +22,6 @@
#pragma once
-#include <libsolidity/analysis/TypeChecker.h>
#include <libsolidity/ast/Types.h>
#include <libsolidity/ast/ASTAnnotations.h>
#include <libsolidity/ast/ASTForward.h>
@@ -33,6 +32,7 @@ namespace dev
namespace solidity
{
+class ErrorReporter;
/**
* The module that performs type analysis on the AST, checks the applicability of operations on
@@ -43,7 +43,7 @@ class TypeChecker: private ASTConstVisitor
{
public:
/// @param _errors the reference to the list of errors and warnings to add them found during type checking.
- TypeChecker(ErrorList& _errors): m_errors(_errors) {}
+ TypeChecker(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {}
/// Performs type checking on the given contract and all of its sub-nodes.
/// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings
@@ -56,14 +56,6 @@ public:
TypePointer const& type(VariableDeclaration const& _variable) const;
private:
- /// Adds a new error to the list of errors.
- void typeError(SourceLocation const& _location, std::string const& _description);
-
- /// Adds a new warning to the list of errors.
- void warning(SourceLocation const& _location, std::string const& _description);
-
- /// Adds a new error to the list of errors and throws to abort type checking.
- void fatalTypeError(SourceLocation const& _location, std::string const& _description);
virtual bool visit(ContractDefinition const& _contract) override;
/// Checks that two functions defined in this contract with the same name have different
@@ -127,7 +119,7 @@ private:
ContractDefinition const* m_scope = nullptr;
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
};
}
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index e79bb6dc..1fc06333 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -520,7 +520,8 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
{
ErrorList errors;
- assembly::CodeGenerator codeGen(errors);
+ ErrorReporter errorReporter(errors);
+ assembly::CodeGenerator codeGen(errorReporter);
unsigned startStackHeight = m_context.stackHeight();
julia::ExternalIdentifierAccess identifierAccess;
identifierAccess.resolve = [&](assembly::Identifier const& _identifier, julia::IdentifierContext)
@@ -648,7 +649,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
m_context.nonConstAssembly(),
identifierAccess
);
- solAssert(Error::containsOnlyWarnings(errors), "Code generation for inline assembly with errors requested.");
+ solAssert(Error::containsOnlyWarnings(errorReporter.errors()), "Code generation for inline assembly with errors requested.");
m_context.setStackOffset(startStackHeight);
return false;
}
diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp
index 77d3c217..fecab2de 100644
--- a/libsolidity/formal/Why3Translator.cpp
+++ b/libsolidity/formal/Why3Translator.cpp
@@ -32,7 +32,7 @@ bool Why3Translator::process(SourceUnit const& _source)
try
{
if (m_lines.size() != 1 || !m_lines.back().contents.empty())
- fatalError(_source, "Multiple source units not yet supported");
+ fatalError(_source, string("Multiple source units not yet supported"));
appendPreface();
_source.accept(*this);
}
@@ -55,22 +55,6 @@ string Why3Translator::translation() const
return result;
}
-void Why3Translator::error(ASTNode const& _node, string const& _description)
-{
- auto err = make_shared<Error>(Error::Type::Why3TranslatorError);
- *err <<
- errinfo_sourceLocation(_node.location()) <<
- errinfo_comment(_description);
- m_errors.push_back(err);
- m_errorOccured = true;
-}
-
-void Why3Translator::fatalError(ASTNode const& _node, string const& _description)
-{
- error(_node, _description);
- BOOST_THROW_EXCEPTION(FatalError());
-}
-
string Why3Translator::toFormalType(Type const& _type) const
{
if (_type.category() == Type::Category::Bool)
@@ -900,3 +884,15 @@ module Address
end
)", 0});
}
+
+void Why3Translator::error(ASTNode const& _source, std::string const& _description)
+{
+ m_errorOccured = true;
+ m_errorReporter.why3TranslatorError(_source, _description);
+}
+void Why3Translator::fatalError(ASTNode const& _source, std::string const& _description)
+{
+ m_errorOccured = true;
+ m_errorReporter.fatalWhy3TranslatorError(_source, _description);
+}
+
diff --git a/libsolidity/formal/Why3Translator.h b/libsolidity/formal/Why3Translator.h
index 03f3bf9c..b48317be 100644
--- a/libsolidity/formal/Why3Translator.h
+++ b/libsolidity/formal/Why3Translator.h
@@ -23,7 +23,7 @@
#pragma once
#include <libsolidity/ast/ASTVisitor.h>
-#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <string>
namespace dev
@@ -43,7 +43,7 @@ class SourceUnit;
class Why3Translator: private ASTConstVisitor
{
public:
- Why3Translator(ErrorList& _errors): m_lines(std::vector<Line>{{std::string(), 0}}), m_errors(_errors) {}
+ Why3Translator(ErrorReporter& _errorReporter): m_lines(std::vector<Line>{{std::string(), 0}}), m_errorReporter(_errorReporter) {}
/// Appends formalisation of the given source unit to the output.
/// @returns false on error.
@@ -52,11 +52,6 @@ public:
std::string translation() const;
private:
- /// Creates an error and adds it to errors list.
- void error(ASTNode const& _node, std::string const& _description);
- /// Reports a fatal error and throws.
- void fatalError(ASTNode const& _node, std::string const& _description);
-
/// Appends imports and constants use throughout the formal code.
void appendPreface();
@@ -65,6 +60,9 @@ private:
using errinfo_noFormalTypeFrom = boost::error_info<struct tag_noFormalTypeFrom, std::string /* name of the type that cannot be translated */ >;
struct NoFormalType: virtual Exception {};
+ void error(ASTNode const& _source, std::string const& _description);
+ void fatalError(ASTNode const& _source, std::string const& _description);
+
void indent() { newLine(); m_lines.back().indentation++; }
void unindent();
void addLine(std::string const& _line);
@@ -98,7 +96,7 @@ private:
virtual bool visitNode(ASTNode const& _node) override
{
- error(_node, "Code not supported for formal verification.");
+ m_errorReporter.why3TranslatorError(_node, "Code not supported for formal verification.");
return false;
}
@@ -142,7 +140,7 @@ private:
unsigned indentation;
};
std::vector<Line> m_lines;
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
};
}
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index 9f512f87..22e43127 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -46,7 +46,7 @@ set<string> const builtinTypes{"bool", "u8", "s8", "u32", "s32", "u64", "s64", "
bool AsmAnalyzer::analyze(Block const& _block)
{
- if (!(ScopeFiller(m_info, m_errors))(_block))
+ if (!(ScopeFiller(m_info, m_errorReporter))(_block))
return false;
return (*this)(_block);
@@ -74,11 +74,10 @@ bool AsmAnalyzer::operator()(assembly::Literal const& _literal)
++m_stackHeight;
if (_literal.kind == assembly::LiteralKind::String && _literal.value.size() > 32)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::TypeError,
- "String literal too long (" + boost::lexical_cast<std::string>(_literal.value.size()) + " > 32)",
- _literal.location
- ));
+ m_errorReporter.typeError(
+ _literal.location,
+ "String literal too long (" + boost::lexical_cast<std::string>(_literal.value.size()) + " > 32)"
+ );
return false;
}
m_info.stackHeightInfo[&_literal] = m_stackHeight;
@@ -87,18 +86,17 @@ bool AsmAnalyzer::operator()(assembly::Literal const& _literal)
bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
{
- size_t numErrorsBefore = m_errors.size();
+ size_t numErrorsBefore = m_errorReporter.errors().size();
bool success = true;
if (m_currentScope->lookup(_identifier.name, Scope::Visitor(
[&](Scope::Variable const& _var)
{
if (!_var.active)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Variable " + _identifier.name + " used before it was declared.",
- _identifier.location
- ));
+ m_errorReporter.declarationError(
+ _identifier.location,
+ "Variable " + _identifier.name + " used before it was declared."
+ );
success = false;
}
++m_stackHeight;
@@ -109,11 +107,10 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
},
[&](Scope::Function const&)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::TypeError,
- "Function " + _identifier.name + " used without being called.",
- _identifier.location
- ));
+ m_errorReporter.typeError(
+ _identifier.location,
+ "Function " + _identifier.name + " used without being called."
+ );
success = false;
}
)))
@@ -127,12 +124,8 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
if (stackSize == size_t(-1))
{
// Only add an error message if the callback did not do it.
- if (numErrorsBefore == m_errors.size())
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Identifier not found.",
- _identifier.location
- ));
+ if (numErrorsBefore == m_errorReporter.errors().size())
+ m_errorReporter.declarationError(_identifier.location, "Identifier not found.");
success = false;
}
m_stackHeight += stackSize == size_t(-1) ? 1 : stackSize;
@@ -187,11 +180,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl)
bool success = boost::apply_visitor(*this, *_varDecl.value);
if ((m_stackHeight - stackHeight) != expectedItems)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Variable count mismatch.",
- _varDecl.location
- ));
+ m_errorReporter.declarationError(_varDecl.location, "Variable count mismatch.");
return false;
}
@@ -233,20 +222,18 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
if (!m_currentScope->lookup(_funCall.functionName.name, Scope::Visitor(
[&](Scope::Variable const&)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::TypeError,
- "Attempt to call variable instead of function.",
- _funCall.functionName.location
- ));
+ m_errorReporter.typeError(
+ _funCall.functionName.location,
+ "Attempt to call variable instead of function."
+ );
success = false;
},
[&](Scope::Label const&)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::TypeError,
- "Attempt to call label instead of function.",
- _funCall.functionName.location
- ));
+ m_errorReporter.typeError(
+ _funCall.functionName.location,
+ "Attempt to call label instead of function."
+ );
success = false;
},
[&](Scope::Function const& _fun)
@@ -257,26 +244,18 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
}
)))
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Function not found.",
- _funCall.functionName.location
- ));
+ m_errorReporter.declarationError(_funCall.functionName.location, "Function not found.");
success = false;
}
if (success)
{
if (_funCall.arguments.size() != arguments)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::TypeError,
- "Expected " +
- boost::lexical_cast<string>(arguments) +
- " arguments but got " +
- boost::lexical_cast<string>(_funCall.arguments.size()) +
- ".",
- _funCall.functionName.location
- ));
+ m_errorReporter.typeError(
+ _funCall.functionName.location,
+ "Expected " + boost::lexical_cast<string>(arguments) + " arguments but got " +
+ boost::lexical_cast<string>(_funCall.arguments.size()) + "."
+ );
success = false;
}
}
@@ -317,11 +296,10 @@ bool AsmAnalyzer::operator()(Switch const& _switch)
auto val = make_tuple(_case.value->kind, _case.value->value);
if (!cases.insert(val).second)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Duplicate case defined",
- _case.location
- ));
+ m_errorReporter.declarationError(
+ _case.location,
+ "Duplicate case defined"
+ );
success = false;
}
}
@@ -354,16 +332,15 @@ bool AsmAnalyzer::operator()(Block const& _block)
int const stackDiff = m_stackHeight - initialStackHeight;
if (stackDiff != 0)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
+ m_errorReporter.declarationError(
+ _block.location,
"Unbalanced stack at the end of a block: " +
(
stackDiff > 0 ?
to_string(stackDiff) + string(" surplus item(s).") :
to_string(-stackDiff) + string(" missing item(s).")
- ),
- _block.location
- ));
+ )
+ );
success = false;
}
@@ -375,27 +352,22 @@ bool AsmAnalyzer::operator()(Block const& _block)
bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t _valueSize)
{
bool success = true;
- size_t numErrorsBefore = m_errors.size();
+ size_t numErrorsBefore = m_errorReporter.errors().size();
size_t variableSize(-1);
if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name))
{
// Check that it is a variable
if (var->type() != typeid(Scope::Variable))
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::TypeError,
- "Assignment requires variable.",
- _variable.location
- ));
+ m_errorReporter.typeError(_variable.location, "Assignment requires variable.");
success = false;
}
else if (!boost::get<Scope::Variable>(*var).active)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Variable " + _variable.name + " used before it was declared.",
- _variable.location
- ));
+ m_errorReporter.declarationError(
+ _variable.location,
+ "Variable " + _variable.name + " used before it was declared."
+ );
success = false;
}
variableSize = 1;
@@ -405,12 +377,8 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t
if (variableSize == size_t(-1))
{
// Only add message if the callback did not.
- if (numErrorsBefore == m_errors.size())
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Variable not found or variable not lvalue.",
- _variable.location
- ));
+ if (numErrorsBefore == m_errorReporter.errors().size())
+ m_errorReporter.declarationError(_variable.location, "Variable not found or variable not lvalue.");
success = false;
}
if (_valueSize == size_t(-1))
@@ -420,15 +388,14 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t
if (_valueSize != variableSize && variableSize != size_t(-1))
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::TypeError,
+ m_errorReporter.typeError(
+ _variable.location,
"Variable size (" +
to_string(variableSize) +
") and value size (" +
to_string(_valueSize) +
- ") do not match.",
- _variable.location
- ));
+ ") do not match."
+ );
success = false;
}
return success;
@@ -439,15 +406,14 @@ bool AsmAnalyzer::expectDeposit(int const _deposit, int const _oldHeight, Source
int stackDiff = m_stackHeight - _oldHeight;
if (stackDiff != _deposit)
{
- m_errors.push_back(make_shared<Error>(
- Error::Type::TypeError,
+ m_errorReporter.typeError(
+ _location,
"Expected instruction(s) to deposit " +
boost::lexical_cast<string>(_deposit) +
" item(s) to the stack, but did deposit " +
boost::lexical_cast<string>(stackDiff) +
- " item(s).",
- _location
- ));
+ " item(s)."
+ );
return false;
}
else
@@ -468,9 +434,8 @@ void AsmAnalyzer::expectValidType(string const& type, SourceLocation const& _loc
return;
if (!builtinTypes.count(type))
- m_errors.push_back(make_shared<Error>(
- Error::Type::TypeError,
- "\"" + type + "\" is not a valid type (user defined types are not yet supported).",
- _location
- ));
+ m_errorReporter.typeError(
+ _location,
+ "\"" + type + "\" is not a valid type (user defined types are not yet supported)."
+ );
}
diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h
index 14b18c4a..7e4d78df 100644
--- a/libsolidity/inlineasm/AsmAnalysis.h
+++ b/libsolidity/inlineasm/AsmAnalysis.h
@@ -22,8 +22,6 @@
#include <libsolidity/inlineasm/AsmStack.h>
-#include <libsolidity/interface/Exceptions.h>
-
#include <boost/variant.hpp>
#include <functional>
@@ -33,6 +31,7 @@ namespace dev
{
namespace solidity
{
+class ErrorReporter;
namespace assembly
{
@@ -63,10 +62,10 @@ class AsmAnalyzer: public boost::static_visitor<bool>
public:
explicit AsmAnalyzer(
AsmAnalysisInfo& _analysisInfo,
- ErrorList& _errors,
+ ErrorReporter& _errorReporter,
bool _julia = false,
julia::ExternalIdentifierAccess::Resolver const& _resolver = julia::ExternalIdentifierAccess::Resolver()
- ): m_resolver(_resolver), m_info(_analysisInfo), m_errors(_errors), m_julia(_julia) {}
+ ): m_resolver(_resolver), m_info(_analysisInfo), m_errorReporter(_errorReporter), m_julia(_julia) {}
bool analyze(assembly::Block const& _block);
@@ -95,7 +94,7 @@ private:
julia::ExternalIdentifierAccess::Resolver const& m_resolver;
Scope* m_currentScope = nullptr;
AsmAnalysisInfo& m_info;
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
bool m_julia = false;
};
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index af3547fd..11494c2d 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -107,7 +107,7 @@ eth::Assembly assembly::CodeGenerator::assemble(
{
eth::Assembly assembly;
EthAssemblyAdapter assemblyAdapter(assembly);
- julia::CodeTransform(m_errors, assemblyAdapter, _parsedData, _analysisInfo, _identifierAccess);
+ julia::CodeTransform(m_errorReporter, assemblyAdapter, _parsedData, _analysisInfo, _identifierAccess);
return assembly;
}
@@ -119,5 +119,5 @@ void assembly::CodeGenerator::assemble(
)
{
EthAssemblyAdapter assemblyAdapter(_assembly);
- julia::CodeTransform(m_errors, assemblyAdapter, _parsedData, _analysisInfo, _identifierAccess);
+ julia::CodeTransform(m_errorReporter, assemblyAdapter, _parsedData, _analysisInfo, _identifierAccess);
}
diff --git a/libsolidity/inlineasm/AsmCodeGen.h b/libsolidity/inlineasm/AsmCodeGen.h
index 1b43d2f6..f075fa93 100644
--- a/libsolidity/inlineasm/AsmCodeGen.h
+++ b/libsolidity/inlineasm/AsmCodeGen.h
@@ -23,7 +23,6 @@
#pragma once
#include <libsolidity/inlineasm/AsmAnalysis.h>
-#include <libsolidity/interface/Exceptions.h>
#include <functional>
@@ -35,6 +34,7 @@ class Assembly;
}
namespace solidity
{
+class ErrorReporter;
namespace assembly
{
struct Block;
@@ -42,8 +42,8 @@ struct Block;
class CodeGenerator
{
public:
- CodeGenerator(ErrorList& _errors):
- m_errors(_errors) {}
+ CodeGenerator(ErrorReporter& _errorReporter):
+ m_errorReporter(_errorReporter) {}
/// Performs code generation and @returns the result.
eth::Assembly assemble(
Block const& _parsedData,
@@ -59,7 +59,7 @@ public:
);
private:
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
};
}
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index 80409c63..0f836406 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -21,10 +21,10 @@
*/
#include <libsolidity/inlineasm/AsmParser.h>
+#include <libsolidity/parsing/Scanner.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <ctype.h>
#include <algorithm>
-#include <libsolidity/parsing/Scanner.h>
-#include <libsolidity/interface/Exceptions.h>
using namespace std;
using namespace dev;
@@ -40,7 +40,7 @@ shared_ptr<assembly::Block> Parser::parse(std::shared_ptr<Scanner> const& _scann
}
catch (FatalError const&)
{
- if (m_errors.empty())
+ if (m_errorReporter.errors().empty())
throw; // Something is weird here, rather throw again.
}
return nullptr;
diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h
index 138af337..e32b1d25 100644
--- a/libsolidity/inlineasm/AsmParser.h
+++ b/libsolidity/inlineasm/AsmParser.h
@@ -37,7 +37,7 @@ namespace assembly
class Parser: public ParserBase
{
public:
- explicit Parser(ErrorList& _errors, bool _julia = false): ParserBase(_errors), m_julia(_julia) {}
+ explicit Parser(ErrorReporter& _errorReporter, bool _julia = false): ParserBase(_errorReporter), m_julia(_julia) {}
/// Parses an inline assembly block starting with `{` and ending with `}`.
/// @returns an empty shared pointer on error.
diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp
index 3fade842..4d26dcf8 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.cpp
+++ b/libsolidity/inlineasm/AsmScopeFiller.cpp
@@ -24,7 +24,7 @@
#include <libsolidity/inlineasm/AsmScope.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
-#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/Utils.h>
#include <boost/range/adaptor/reversed.hpp>
@@ -37,8 +37,8 @@ using namespace dev;
using namespace dev::solidity;
using namespace dev::solidity::assembly;
-ScopeFiller::ScopeFiller(AsmAnalysisInfo& _info, ErrorList& _errors):
- m_info(_info), m_errors(_errors)
+ScopeFiller::ScopeFiller(AsmAnalysisInfo& _info, ErrorReporter& _errorReporter):
+ m_info(_info), m_errorReporter(_errorReporter)
{
m_currentScope = &scope(nullptr);
}
@@ -48,11 +48,10 @@ bool ScopeFiller::operator()(Label const& _item)
if (!m_currentScope->registerLabel(_item.name))
{
//@TODO secondary location
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Label name " + _item.name + " already taken in this scope.",
- _item.location
- ));
+ m_errorReporter.declarationError(
+ _item.location,
+ "Label name " + _item.name + " already taken in this scope."
+ );
return false;
}
return true;
@@ -78,11 +77,10 @@ bool ScopeFiller::operator()(assembly::FunctionDefinition const& _funDef)
if (!m_currentScope->registerFunction(_funDef.name, arguments, returns))
{
//@TODO secondary location
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Function name " + _funDef.name + " already taken in this scope.",
- _funDef.location
- ));
+ m_errorReporter.declarationError(
+ _funDef.location,
+ "Function name " + _funDef.name + " already taken in this scope."
+ );
success = false;
}
@@ -132,11 +130,10 @@ bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const&
if (!_scope.registerVariable(_name.name, _name.type))
{
//@TODO secondary location
- m_errors.push_back(make_shared<Error>(
- Error::Type::DeclarationError,
- "Variable name " + _name.name + " already taken in this scope.",
- _location
- ));
+ m_errorReporter.declarationError(
+ _location,
+ "Variable name " + _name.name + " already taken in this scope."
+ );
return false;
}
return true;
diff --git a/libsolidity/inlineasm/AsmScopeFiller.h b/libsolidity/inlineasm/AsmScopeFiller.h
index 42e80141..1166d50f 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.h
+++ b/libsolidity/inlineasm/AsmScopeFiller.h
@@ -20,8 +20,6 @@
#pragma once
-#include <libsolidity/interface/Exceptions.h>
-
#include <boost/variant.hpp>
#include <functional>
@@ -29,8 +27,10 @@
namespace dev
{
+struct SourceLocation;
namespace solidity
{
+class ErrorReporter;
namespace assembly
{
@@ -58,7 +58,7 @@ struct AsmAnalysisInfo;
class ScopeFiller: public boost::static_visitor<bool>
{
public:
- ScopeFiller(AsmAnalysisInfo& _info, ErrorList& _errors);
+ ScopeFiller(AsmAnalysisInfo& _info, ErrorReporter& _errorReporter);
bool operator()(assembly::Instruction const&) { return true; }
bool operator()(assembly::Literal const&) { return true; }
@@ -84,7 +84,7 @@ private:
Scope* m_currentScope = nullptr;
AsmAnalysisInfo& m_info;
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
};
}
diff --git a/libsolidity/inlineasm/AsmStack.cpp b/libsolidity/inlineasm/AsmStack.cpp
index fe443c08..73b1604d 100644
--- a/libsolidity/inlineasm/AsmStack.cpp
+++ b/libsolidity/inlineasm/AsmStack.cpp
@@ -46,14 +46,14 @@ bool InlineAssemblyStack::parse(
)
{
m_parserResult = make_shared<Block>();
- Parser parser(m_errors);
+ Parser parser(m_errorReporter);
auto result = parser.parse(_scanner);
if (!result)
return false;
*m_parserResult = std::move(*result);
AsmAnalysisInfo analysisInfo;
- return (AsmAnalyzer(analysisInfo, m_errors, false, _resolver)).analyze(*m_parserResult);
+ return (AsmAnalyzer(analysisInfo, m_errorReporter, false, _resolver)).analyze(*m_parserResult);
}
string InlineAssemblyStack::toString()
@@ -64,9 +64,9 @@ string InlineAssemblyStack::toString()
eth::Assembly InlineAssemblyStack::assemble()
{
AsmAnalysisInfo analysisInfo;
- AsmAnalyzer analyzer(analysisInfo, m_errors);
+ AsmAnalyzer analyzer(analysisInfo, m_errorReporter);
solAssert(analyzer.analyze(*m_parserResult), "");
- CodeGenerator codeGen(m_errors);
+ CodeGenerator codeGen(m_errorReporter);
return codeGen.assemble(*m_parserResult, analysisInfo);
}
@@ -77,19 +77,20 @@ bool InlineAssemblyStack::parseAndAssemble(
)
{
ErrorList errors;
+ ErrorReporter errorReporter(errors);
auto scanner = make_shared<Scanner>(CharStream(_input), "--CODEGEN--");
- auto parserResult = Parser(errors).parse(scanner);
- if (!errors.empty())
+ auto parserResult = Parser(errorReporter).parse(scanner);
+ if (!errorReporter.errors().empty())
return false;
solAssert(parserResult, "");
AsmAnalysisInfo analysisInfo;
- AsmAnalyzer analyzer(analysisInfo, errors, false, _identifierAccess.resolve);
+ AsmAnalyzer analyzer(analysisInfo, errorReporter, false, _identifierAccess.resolve);
solAssert(analyzer.analyze(*parserResult), "");
- CodeGenerator(errors).assemble(*parserResult, analysisInfo, _assembly, _identifierAccess);
+ CodeGenerator(errorReporter).assemble(*parserResult, analysisInfo, _assembly, _identifierAccess);
// At this point, the assembly might be messed up, but we should throw an
// internal compiler error anyway.
- return errors.empty();
+ return errorReporter.errors().empty();
}
diff --git a/libsolidity/inlineasm/AsmStack.h b/libsolidity/inlineasm/AsmStack.h
index 23072a88..7452804d 100644
--- a/libsolidity/inlineasm/AsmStack.h
+++ b/libsolidity/inlineasm/AsmStack.h
@@ -22,9 +22,8 @@
#pragma once
-#include <libsolidity/interface/Exceptions.h>
-
#include <libjulia/backends/evm/AbstractAssembly.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <string>
#include <functional>
@@ -46,6 +45,8 @@ struct Identifier;
class InlineAssemblyStack
{
public:
+ InlineAssemblyStack():
+ m_errorReporter(m_errorList) {}
/// Parse the given inline assembly chunk starting with `{` and ending with the corresponding `}`.
/// @return false or error.
bool parse(
@@ -65,11 +66,12 @@ public:
julia::ExternalIdentifierAccess const& _identifierAccess = julia::ExternalIdentifierAccess()
);
- ErrorList const& errors() const { return m_errors; }
+ ErrorList const& errors() const { return m_errorReporter.errors(); }
private:
std::shared_ptr<Block> m_parserResult;
- ErrorList m_errors;
+ ErrorList m_errorList;
+ ErrorReporter m_errorReporter;
};
}
diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp
index c4bd63c4..b027ac3c 100644
--- a/libsolidity/interface/AssemblyStack.cpp
+++ b/libsolidity/interface/AssemblyStack.cpp
@@ -45,13 +45,13 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string
{
m_analysisSuccessful = false;
m_scanner = make_shared<Scanner>(CharStream(_source), _sourceName);
- m_parserResult = assembly::Parser(m_errors, m_language == Language::JULIA).parse(m_scanner);
- if (!m_errors.empty())
+ m_parserResult = assembly::Parser(m_errorReporter, m_language == Language::JULIA).parse(m_scanner);
+ if (!m_errorReporter.errors().empty())
return false;
solAssert(m_parserResult, "");
m_analysisInfo = make_shared<assembly::AsmAnalysisInfo>();
- assembly::AsmAnalyzer analyzer(*m_analysisInfo, m_errors);
+ assembly::AsmAnalyzer analyzer(*m_analysisInfo, m_errorReporter);
m_analysisSuccessful = analyzer.analyze(*m_parserResult);
return m_analysisSuccessful;
}
@@ -66,7 +66,7 @@ eth::LinkerObject AssemblyStack::assemble(Machine _machine)
{
case Machine::EVM:
{
- auto assembly = assembly::CodeGenerator(m_errors).assemble(*m_parserResult, *m_analysisInfo);
+ auto assembly = assembly::CodeGenerator(m_errorReporter).assemble(*m_parserResult, *m_analysisInfo);
return assembly.assemble();
}
case Machine::EVM15:
diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h
index 40662ac3..62a5134a 100644
--- a/libsolidity/interface/AssemblyStack.h
+++ b/libsolidity/interface/AssemblyStack.h
@@ -21,8 +21,8 @@
#pragma once
-#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <libevmasm/LinkerObject.h>
#include <string>
@@ -50,7 +50,7 @@ public:
enum class Machine { EVM, EVM15, eWasm };
explicit AssemblyStack(Language _language = Language::Assembly):
- m_language(_language)
+ m_language(_language), m_errorReporter(m_errors)
{}
/// @returns the scanner used during parsing
@@ -79,6 +79,7 @@ private:
std::shared_ptr<assembly::Block> m_parserResult;
std::shared_ptr<assembly::AsmAnalysisInfo> m_analysisInfo;
ErrorList m_errors;
+ ErrorReporter m_errorReporter;
};
}
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 328df91f..44220402 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -57,9 +57,6 @@ using namespace std;
using namespace dev;
using namespace dev::solidity;
-CompilerStack::CompilerStack(ReadFile::Callback const& _readFile):
- m_readFile(_readFile) {}
-
void CompilerStack::setRemappings(vector<string> const& _remappings)
{
vector<Remapping> remappings;
@@ -96,7 +93,7 @@ void CompilerStack::reset(bool _keepSources)
m_scopes.clear();
m_sourceOrder.clear();
m_contracts.clear();
- m_errors.clear();
+ m_errorReporter.clear();
m_stackState = Empty;
}
@@ -121,15 +118,11 @@ bool CompilerStack::parse()
//reset
if(m_stackState != SourcesSet)
return false;
- m_errors.clear();
+ m_errorReporter.clear();
ASTNode::resetID();
if (SemVerVersion{string(VersionString)}.isPrerelease())
- {
- auto err = make_shared<Error>(Error::Type::Warning);
- *err << errinfo_comment("This is a pre-release compiler version, please do not use it in production.");
- m_errors.push_back(err);
- }
+ m_errorReporter.warning("This is a pre-release compiler version, please do not use it in production.");
vector<string> sourcesToParse;
for (auto const& s: m_sources)
@@ -139,9 +132,9 @@ bool CompilerStack::parse()
string const& path = sourcesToParse[i];
Source& source = m_sources[path];
source.scanner->reset();
- source.ast = Parser(m_errors).parse(source.scanner);
+ source.ast = Parser(m_errorReporter).parse(source.scanner);
if (!source.ast)
- solAssert(!Error::containsOnlyWarnings(m_errors), "Parser returned null but did not report error.");
+ solAssert(!Error::containsOnlyWarnings(m_errorReporter.errors()), "Parser returned null but did not report error.");
else
{
source.ast->annotation().path = path;
@@ -154,7 +147,7 @@ bool CompilerStack::parse()
}
}
}
- if (Error::containsOnlyWarnings(m_errors))
+ if (Error::containsOnlyWarnings(m_errorReporter.errors()))
{
m_stackState = ParsingSuccessful;
return true;
@@ -170,18 +163,18 @@ bool CompilerStack::analyze()
resolveImports();
bool noErrors = true;
- SyntaxChecker syntaxChecker(m_errors);
+ SyntaxChecker syntaxChecker(m_errorReporter);
for (Source const* source: m_sourceOrder)
if (!syntaxChecker.checkSyntax(*source->ast))
noErrors = false;
- DocStringAnalyser docStringAnalyser(m_errors);
+ DocStringAnalyser docStringAnalyser(m_errorReporter);
for (Source const* source: m_sourceOrder)
if (!docStringAnalyser.analyseDocStrings(*source->ast))
noErrors = false;
m_globalContext = make_shared<GlobalContext>();
- NameAndTypeResolver resolver(m_globalContext->declarations(), m_scopes, m_errors);
+ NameAndTypeResolver resolver(m_globalContext->declarations(), m_scopes, m_errorReporter);
for (Source const* source: m_sourceOrder)
if (!resolver.registerDeclarations(*source->ast))
return false;
@@ -217,7 +210,7 @@ bool CompilerStack::analyze()
{
m_globalContext->setCurrentContract(*contract);
resolver.updateDeclaration(*m_globalContext->currentThis());
- TypeChecker typeChecker(m_errors);
+ TypeChecker typeChecker(m_errorReporter);
if (typeChecker.checkTypeRequirements(*contract))
{
contract->setDevDocumentation(Natspec::devDocumentation(*contract));
@@ -237,7 +230,7 @@ bool CompilerStack::analyze()
if (noErrors)
{
- PostTypeChecker postTypeChecker(m_errors);
+ PostTypeChecker postTypeChecker(m_errorReporter);
for (Source const* source: m_sourceOrder)
if (!postTypeChecker.check(*source->ast))
noErrors = false;
@@ -245,7 +238,7 @@ bool CompilerStack::analyze()
if (noErrors)
{
- StaticAnalyzer staticAnalyzer(m_errors);
+ StaticAnalyzer staticAnalyzer(m_errorReporter);
for (Source const* source: m_sourceOrder)
if (!staticAnalyzer.analyze(*source->ast))
noErrors = false;
@@ -323,11 +316,11 @@ void CompilerStack::link()
}
}
-bool CompilerStack::prepareFormalAnalysis(ErrorList* _errors)
+bool CompilerStack::prepareFormalAnalysis(ErrorReporter* _errorReporter)
{
- if (!_errors)
- _errors = &m_errors;
- Why3Translator translator(*_errors);
+ if (!_errorReporter)
+ _errorReporter = &m_errorReporter;
+ Why3Translator translator(*_errorReporter);
for (Source const* source: m_sourceOrder)
if (!translator.process(*source->ast))
return false;
@@ -582,11 +575,10 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast, std::string
newSources[importPath] = result.contentsOrErrorMessage;
else
{
- auto err = make_shared<Error>(Error::Type::ParserError);
- *err <<
- errinfo_sourceLocation(import->location()) <<
- errinfo_comment("Source \"" + importPath + "\" not found: " + result.contentsOrErrorMessage);
- m_errors.push_back(std::move(err));
+ m_errorReporter.parserError(
+ import->location(),
+ string("Source \"" + importPath + "\" not found: " + result.contentsOrErrorMessage)
+ );
continue;
}
}
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 84d15d70..76d36c7b 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -35,7 +35,7 @@
#include <libdevcore/FixedHash.h>
#include <libevmasm/SourceLocation.h>
#include <libevmasm/LinkerObject.h>
-#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/ReadFile.h>
namespace dev
@@ -80,7 +80,10 @@ public:
/// Creates a new compiler stack.
/// @param _readFile callback to used to read files for import statements. Must return
/// and must not emit exceptions.
- explicit CompilerStack(ReadFile::Callback const& _readFile = ReadFile::Callback());
+ explicit CompilerStack(ReadFile::Callback const& _readFile = ReadFile::Callback()):
+ m_readFile(_readFile),
+ m_errorList(),
+ m_errorReporter(m_errorList) {}
/// Sets path remappings in the format "context:prefix=target"
void setRemappings(std::vector<std::string> const& _remappings);
@@ -130,7 +133,7 @@ public:
/// Tries to translate all source files into a language suitable for formal analysis.
/// @param _errors list to store errors - defaults to the internal error list.
/// @returns false on error.
- bool prepareFormalAnalysis(ErrorList* _errors = nullptr);
+ bool prepareFormalAnalysis(ErrorReporter* _errorReporter = nullptr);
std::string const& formalTranslation() const { return m_formalTranslation; }
/// @returns the assembled object for a contract.
@@ -207,7 +210,7 @@ public:
std::tuple<int, int, int, int> positionFromSourceLocation(SourceLocation const& _sourceLocation) const;
/// @returns the list of errors that occured during parsing and type checking.
- ErrorList const& errors() const { return m_errors; }
+ ErrorList const& errors() { return m_errorReporter.errors(); }
private:
/**
@@ -289,7 +292,8 @@ private:
std::vector<Source const*> m_sourceOrder;
std::map<std::string const, Contract> m_contracts;
std::string m_formalTranslation;
- ErrorList m_errors;
+ ErrorList m_errorList;
+ ErrorReporter m_errorReporter;
bool m_metadataLiteralSources = false;
State m_stackState = Empty;
};
diff --git a/libsolidity/interface/ErrorReporter.cpp b/libsolidity/interface/ErrorReporter.cpp
new file mode 100644
index 00000000..2cbb952c
--- /dev/null
+++ b/libsolidity/interface/ErrorReporter.cpp
@@ -0,0 +1,186 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Rhett <roadriverrail@gmail.com>
+ * @date 2017
+ * Error helper class.
+ */
+
+#include <libsolidity/interface/ErrorReporter.h>
+#include <libsolidity/ast/AST.h>
+#include <memory>
+
+using namespace std;
+using namespace dev;
+using namespace dev::solidity;
+
+ErrorReporter& ErrorReporter::operator=(ErrorReporter const& _errorReporter)
+{
+ if (&_errorReporter == this)
+ return *this;
+ m_errorList = _errorReporter.m_errorList;
+ return *this;
+}
+
+
+void ErrorReporter::warning(string const& _description)
+{
+ error(Error::Type::Warning, SourceLocation(), _description);
+}
+
+void ErrorReporter::warning(SourceLocation const& _location, string const& _description)
+{
+ error(Error::Type::Warning, _location, _description);
+}
+
+void ErrorReporter::error(Error::Type _type, SourceLocation const& _location, string const& _description)
+{
+ auto err = make_shared<Error>(_type);
+ *err <<
+ errinfo_sourceLocation(_location) <<
+ errinfo_comment(_description);
+
+ m_errorList.push_back(err);
+}
+
+void ErrorReporter::error(Error::Type _type, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, string const& _description)
+{
+ auto err = make_shared<Error>(_type);
+ *err <<
+ errinfo_sourceLocation(_location) <<
+ errinfo_secondarySourceLocation(_secondaryLocation) <<
+ errinfo_comment(_description);
+
+ m_errorList.push_back(err);
+}
+
+
+void ErrorReporter::fatalError(Error::Type _type, SourceLocation const& _location, string const& _description)
+{
+ error(_type, _location, _description);
+ BOOST_THROW_EXCEPTION(FatalError());
+}
+
+ErrorList const& ErrorReporter::errors() const
+{
+ return m_errorList;
+}
+
+void ErrorReporter::clear()
+{
+ m_errorList.clear();
+}
+
+void ErrorReporter::declarationError(SourceLocation const& _location, SecondarySourceLocation const&_secondaryLocation, string const& _description)
+{
+ error(
+ Error::Type::DeclarationError,
+ _location,
+ _secondaryLocation,
+ _description
+ );
+}
+
+void ErrorReporter::declarationError(SourceLocation const& _location, string const& _description)
+{
+ error(
+ Error::Type::DeclarationError,
+ _location,
+ _description
+ );
+}
+
+void ErrorReporter::fatalDeclarationError(SourceLocation const& _location, std::string const& _description)
+{
+ fatalError(
+ Error::Type::DeclarationError,
+ _location,
+ _description);
+}
+
+void ErrorReporter::parserError(SourceLocation const& _location, string const& _description)
+{
+ error(
+ Error::Type::ParserError,
+ _location,
+ _description
+ );
+}
+
+void ErrorReporter::fatalParserError(SourceLocation const& _location, string const& _description)
+{
+ fatalError(
+ Error::Type::ParserError,
+ _location,
+ _description
+ );
+}
+
+void ErrorReporter::syntaxError(SourceLocation const& _location, string const& _description)
+{
+ error(
+ Error::Type::SyntaxError,
+ _location,
+ _description
+ );
+}
+
+void ErrorReporter::typeError(SourceLocation const& _location, string const& _description)
+{
+ error(
+ Error::Type::TypeError,
+ _location,
+ _description
+ );
+}
+
+
+void ErrorReporter::fatalTypeError(SourceLocation const& _location, string const& _description)
+{
+ fatalError(Error::Type::TypeError,
+ _location,
+ _description
+ );
+}
+
+void ErrorReporter::docstringParsingError(string const& _description)
+{
+ error(
+ Error::Type::DocstringParsingError,
+ SourceLocation(),
+ _description
+ );
+}
+
+void ErrorReporter::why3TranslatorError(ASTNode const& _location, std::string const& _description)
+{
+ error(
+ Error::Type::Why3TranslatorError,
+ _location.location(),
+ _description
+ );
+}
+
+void ErrorReporter::fatalWhy3TranslatorError(ASTNode const& _location, std::string const& _description)
+{
+ fatalError(
+ Error::Type::Why3TranslatorError,
+ _location.location(),
+ _description
+ );
+}
+
diff --git a/libsolidity/interface/ErrorReporter.h b/libsolidity/interface/ErrorReporter.h
new file mode 100644
index 00000000..83324446
--- /dev/null
+++ b/libsolidity/interface/ErrorReporter.h
@@ -0,0 +1,106 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Rhett <roadriverrail@gmail.com>
+ * @date 2017
+ * Error reporting helper class.
+ */
+
+#pragma once
+
+#include <libsolidity/interface/Exceptions.h>
+#include <libevmasm/SourceLocation.h>
+
+namespace dev
+{
+namespace solidity
+{
+
+class ASTNode;
+
+class ErrorReporter
+{
+public:
+
+ ErrorReporter(ErrorList& _errors):
+ m_errorList(_errors) { }
+
+ ErrorReporter& operator=(ErrorReporter const& _errorReporter);
+
+ void warning(std::string const& _description = std::string());
+
+ void warning(
+ SourceLocation const& _location = SourceLocation(),
+ std::string const& _description = std::string()
+ );
+
+ void error(
+ Error::Type _type,
+ SourceLocation const& _location = SourceLocation(),
+ std::string const& _description = std::string()
+ );
+
+ void declarationError(
+ SourceLocation const& _location,
+ SecondarySourceLocation const& _secondaryLocation = SecondarySourceLocation(),
+ std::string const& _description = std::string()
+ );
+
+ void declarationError(
+ SourceLocation const& _location,
+ std::string const& _description = std::string()
+ );
+
+ void fatalDeclarationError(SourceLocation const& _location, std::string const& _description);
+
+ void parserError(SourceLocation const& _location, std::string const& _description);
+
+ void fatalParserError(SourceLocation const& _location, std::string const& _description);
+
+ void syntaxError(SourceLocation const& _location, std::string const& _description);
+
+ void typeError(SourceLocation const& _location, std::string const& _description);
+
+ void fatalTypeError(SourceLocation const& _location, std::string const& _description);
+
+ void docstringParsingError(std::string const& _location);
+
+ void why3TranslatorError(ASTNode const& _location, std::string const& _description);
+
+ void fatalWhy3TranslatorError(ASTNode const& _location, std::string const& _description);
+
+ ErrorList const& errors() const;
+
+ void clear();
+
+private:
+ void error(Error::Type _type,
+ SourceLocation const& _location,
+ SecondarySourceLocation const& _secondaryLocation,
+ std::string const& _description = std::string());
+
+ void fatalError(Error::Type _type,
+ SourceLocation const& _location = SourceLocation(),
+ std::string const& _description = std::string());
+
+ ErrorList& m_errorList;
+};
+
+
+}
+}
+
diff --git a/libsolidity/parsing/DocStringParser.cpp b/libsolidity/parsing/DocStringParser.cpp
index 8e912126..cd6c1d8a 100644
--- a/libsolidity/parsing/DocStringParser.cpp
+++ b/libsolidity/parsing/DocStringParser.cpp
@@ -1,5 +1,6 @@
#include <libsolidity/parsing/DocStringParser.h>
+#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/Utils.h>
#include <boost/range/irange.hpp>
@@ -51,9 +52,9 @@ string::const_iterator skipWhitespace(
}
-bool DocStringParser::parse(string const& _docString, ErrorList& _errors)
+bool DocStringParser::parse(string const& _docString, ErrorReporter& _errorReporter)
{
- m_errors = &_errors;
+ m_errorReporter = &_errorReporter;
m_errorsOccurred = false;
m_lastTag = nullptr;
@@ -172,8 +173,6 @@ void DocStringParser::newTag(string const& _tagName)
void DocStringParser::appendError(string const& _description)
{
- auto err = make_shared<Error>(Error::Type::DocstringParsingError);
- *err << errinfo_comment(_description);
- m_errors->push_back(err);
m_errorsOccurred = true;
+ m_errorReporter->docstringParsingError(_description);
}
diff --git a/libsolidity/parsing/DocStringParser.h b/libsolidity/parsing/DocStringParser.h
index c7f81c55..5f2819cc 100644
--- a/libsolidity/parsing/DocStringParser.h
+++ b/libsolidity/parsing/DocStringParser.h
@@ -23,7 +23,6 @@
#pragma once
#include <string>
-#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/ast/ASTAnnotations.h>
namespace dev
@@ -31,12 +30,14 @@ namespace dev
namespace solidity
{
+class ErrorReporter;
+
class DocStringParser
{
public:
/// Parse the given @a _docString and stores the parsed components internally.
/// @returns false on error and appends the error to @a _errors.
- bool parse(std::string const& _docString, ErrorList& _errors);
+ bool parse(std::string const& _docString, ErrorReporter& _errorReporter);
std::multimap<std::string, DocTag> const& tags() const { return m_docTags; }
@@ -62,7 +63,7 @@ private:
/// Mapping tag name -> content.
std::multimap<std::string, DocTag> m_docTags;
DocTag* m_lastTag = nullptr;
- ErrorList* m_errors = nullptr;
+ ErrorReporter* m_errorReporter = nullptr;
bool m_errorsOccurred = false;
};
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 5b318b2b..ec27f89b 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -26,7 +26,7 @@
#include <libsolidity/parsing/Parser.h>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/inlineasm/AsmParser.h>
-#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/interface/ErrorReporter.h>
using namespace std;
@@ -94,7 +94,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
}
catch (FatalError const&)
{
- if (m_errors.empty())
+ if (m_errorReporter.errors().empty())
throw; // Something is weird here, rather throw again.
return nullptr;
}
@@ -865,7 +865,7 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
m_scanner->next();
}
- assembly::Parser asmParser(m_errors);
+ assembly::Parser asmParser(m_errorReporter);
shared_ptr<assembly::Block> block = asmParser.parse(m_scanner);
nodeFactory.markEndPosition();
return nodeFactory.createNode<InlineAssembly>(_docString, block);
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index 5ec3dbed..19631c58 100644
--- a/libsolidity/parsing/Parser.h
+++ b/libsolidity/parsing/Parser.h
@@ -35,7 +35,7 @@ class Scanner;
class Parser: public ParserBase
{
public:
- Parser(ErrorList& _errors): ParserBase(_errors) {}
+ Parser(ErrorReporter& _errorReporter): ParserBase(_errorReporter) {}
ASTPointer<SourceUnit> parse(std::shared_ptr<Scanner> const& _scanner);
diff --git a/libsolidity/parsing/ParserBase.cpp b/libsolidity/parsing/ParserBase.cpp
index ac103bda..9987b82c 100644
--- a/libsolidity/parsing/ParserBase.cpp
+++ b/libsolidity/parsing/ParserBase.cpp
@@ -22,6 +22,7 @@
#include <libsolidity/parsing/ParserBase.h>
#include <libsolidity/parsing/Scanner.h>
+#include <libsolidity/interface/ErrorReporter.h>
using namespace std;
using namespace dev;
@@ -82,16 +83,10 @@ void ParserBase::expectToken(Token::Value _value)
void ParserBase::parserError(string const& _description)
{
- auto err = make_shared<Error>(Error::Type::ParserError);
- *err <<
- errinfo_sourceLocation(SourceLocation(position(), position(), sourceName())) <<
- errinfo_comment(_description);
-
- m_errors.push_back(err);
+ m_errorReporter.parserError(SourceLocation(position(), position(), sourceName()), _description);
}
void ParserBase::fatalParserError(string const& _description)
{
- parserError(_description);
- BOOST_THROW_EXCEPTION(FatalError());
+ m_errorReporter.fatalParserError(SourceLocation(position(), position(), sourceName()), _description);
}
diff --git a/libsolidity/parsing/ParserBase.h b/libsolidity/parsing/ParserBase.h
index 18b39a5e..ae56cead 100644
--- a/libsolidity/parsing/ParserBase.h
+++ b/libsolidity/parsing/ParserBase.h
@@ -23,7 +23,6 @@
#pragma once
#include <memory>
-#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/parsing/Token.h>
@@ -32,12 +31,13 @@ namespace dev
namespace solidity
{
+class ErrorReporter;
class Scanner;
class ParserBase
{
public:
- ParserBase(ErrorList& errors): m_errors(errors) {}
+ ParserBase(ErrorReporter& errorReporter): m_errorReporter(errorReporter) {}
std::shared_ptr<std::string const> const& sourceName() const;
@@ -67,7 +67,7 @@ protected:
std::shared_ptr<Scanner> m_scanner;
/// The reference to the list of errors and warning to add errors/warnings during parsing
- ErrorList& m_errors;
+ ErrorReporter& m_errorReporter;
};
}