added Error class for all kind of errors

Conflicts:
	libsolidity/Exceptions.h
This commit is contained in:
LianaHus 2015-10-02 14:41:40 +02:00
parent 95ad872678
commit 742e5b259a
16 changed files with 107 additions and 76 deletions

View File

@ -51,9 +51,9 @@ ASTAnnotation& ASTNode::annotation() const
return *m_annotation;
}
TypeError ASTNode::createTypeError(string const& _description) const
Error ASTNode::createTypeError(string const& _description) const
{
return TypeError() << errinfo_sourceLocation(location()) << errinfo_comment(_description);
return Error(Error::Type::TypeError) << errinfo_sourceLocation(location()) << errinfo_comment(_description);
}
map<FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions() const

View File

@ -75,7 +75,7 @@ public:
/// Creates a @ref TypeError exception and decorates it with the location of the node and
/// the given description
TypeError createTypeError(std::string const& _description) const;
Error createTypeError(std::string const& _description) const;
///@todo make this const-safe by providing a different way to access the annotation
virtual ASTAnnotation& annotation() const;
@ -660,10 +660,14 @@ class MagicVariableDeclaration: public Declaration
public:
MagicVariableDeclaration(ASTString const& _name, std::shared_ptr<Type const> const& _type):
Declaration(SourceLocation(), std::make_shared<ASTString>(_name)), m_type(_type) {}
virtual void accept(ASTVisitor&) override { BOOST_THROW_EXCEPTION(InternalCompilerError()
<< errinfo_comment("MagicVariableDeclaration used inside real AST.")); }
virtual void accept(ASTConstVisitor&) const override { BOOST_THROW_EXCEPTION(InternalCompilerError()
<< errinfo_comment("MagicVariableDeclaration used inside real AST.")); }
virtual void accept(ASTVisitor&) override
{
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("MagicVariableDeclaration used inside real AST."));
}
virtual void accept(ASTConstVisitor&) const override
{
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("MagicVariableDeclaration used inside real AST."));
}
virtual TypePointer type(ContractDefinition const*) const override { return m_type; }

View File

@ -107,7 +107,7 @@ bool CompilerStack::parse()
resolveImports();
m_globalContext = make_shared<GlobalContext>();
NameAndTypeResolver resolver(m_globalContext->declarations());
NameAndTypeResolver resolver(m_globalContext->declarations(), m_errors);
for (Source const* source: m_sourceOrder)
resolver.registerDeclarations(*source->ast);
for (Source const* source: m_sourceOrder)
@ -345,7 +345,7 @@ void CompilerStack::resolveImports()
string const& id = import->identifier();
if (!m_sources.count(id))
BOOST_THROW_EXCEPTION(
ParserError()
Error(Error::Type::ParserError)
<< errinfo_sourceLocation(import->location())
<< errinfo_comment("Source not found.")
);

View File

@ -33,6 +33,7 @@
#include <libdevcore/FixedHash.h>
#include <libevmasm/SourceLocation.h>
#include <libevmasm/LinkerObject.h>
#include <libsolidity/Exceptions.h>
namespace dev
{
@ -164,7 +165,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.
std::vector<std::shared_ptr<Error const>> const& errors() const { return m_errors; }
ErrorList const& errors() const { return m_errors; }
private:
/**
@ -212,7 +213,7 @@ private:
std::shared_ptr<GlobalContext> m_globalContext;
std::vector<Source const*> m_sourceOrder;
std::map<std::string const, Contract> m_contracts;
std::vector<std::shared_ptr<Error const>> m_errors;
ErrorList m_errors;
};
}

View File

@ -31,13 +31,51 @@ namespace dev
{
namespace solidity
{
struct Error: virtual Exception {};
struct ParserError: virtual Error {};
struct TypeError: virtual Error {};
struct DeclarationError: virtual Error {};
struct DocstringParsingError: virtual Error {};
struct Warning: virtual Error {};
class Error: virtual public Exception
{
public:
enum class Type
{
DeclarationError,
DocstringParsingError,
ParserError,
TypeError,
Warning
};
Error(Type _type) : m_type(_type)
{
switch(m_type)
{
case Type::DeclarationError:
m_typeName = "Declaration Error";
break;
case Type::DocstringParsingError:
m_typeName = "Docstring Parsing Error";
break;
case Type::ParserError:
m_typeName = "Parser Error";
break;
case Type::TypeError:
m_typeName = "Type Error";
break;
case Type::Warning:
m_typeName = "Warning";
break;
default:
m_typeName = "Error";
break;
}
}
Type type() { return m_type; }
std::string const& typeName() const { return m_typeName; }
private:
Type m_type;
std::string m_typeName;
};
struct CompilerError: virtual Exception {};
struct InternalCompilerError: virtual Exception {};
@ -56,6 +94,8 @@ public:
std::vector<errorSourceLocationInfo> infos;
};
using ErrorList = std::vector<std::shared_ptr<Error const>>;
using errinfo_sourceLocation = boost::error_info<struct tag_sourceLocation, SourceLocation>;
using errinfo_secondarySourceLocation = boost::error_info<struct tag_secondarySourceLocation, SecondarySourceLocation>;

View File

@ -243,7 +243,7 @@ string InterfaceHandler::devDocumentation(ContractDefinition const& _contractDef
if (find(paramNames.begin(), paramNames.end(), pair.first) == paramNames.end())
// LTODO: mismatching parameter name, throw some form of warning and not just an exception
BOOST_THROW_EXCEPTION(
DocstringParsingError() <<
Error(Error::Type::DocstringParsingError) <<
errinfo_comment("documented parameter \"" + pair.first + "\" not found in the parameter list of the function.")
);
params[pair.first] = pair.second;
@ -310,7 +310,7 @@ string::const_iterator InterfaceHandler::parseDocTagParam(
// find param name
auto currPos = find(_pos, _end, ' ');
if (currPos == _end)
BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("End of param name not found" + string(_pos, _end)));
BOOST_THROW_EXCEPTION(Error(Error::Type::DocstringParsingError) << errinfo_comment("End of param name not found" + string(_pos, _end)));
auto paramName = string(_pos, currPos);
@ -369,7 +369,7 @@ string::const_iterator InterfaceHandler::parseDocTag(
return parseDocTagLine(_pos, _end, m_author, DocTagType::Author, false);
else
// LTODO: for now this else makes no sense but later comments will go to more language constructs
BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("@author tag is legal only for contracts"));
BOOST_THROW_EXCEPTION(Error(Error::Type::DocstringParsingError) << errinfo_comment("@author tag is legal only for contracts"));
}
else if (_tag == "title")
{
@ -377,13 +377,13 @@ string::const_iterator InterfaceHandler::parseDocTag(
return parseDocTagLine(_pos, _end, m_title, DocTagType::Title, false);
else
// LTODO: Unknown tag, throw some form of warning and not just an exception
BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("@title tag is legal only for contracts"));
BOOST_THROW_EXCEPTION(Error(Error::Type::DocstringParsingError) << errinfo_comment("@title tag is legal only for contracts"));
}
else if (_tag == "param")
return parseDocTagParam(_pos, _end);
else
// LTODO: Unknown tag, throw some form of warning and not just an exception
BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("Unknown tag " + _tag + " encountered"));
BOOST_THROW_EXCEPTION(Error(Error::Type::DocstringParsingError) << errinfo_comment("Unknown tag " + _tag + " encountered"));
}
else
return appendDocTag(_pos, _end, _owner);
@ -410,13 +410,13 @@ string::const_iterator InterfaceHandler::appendDocTag(
return parseDocTagLine(_pos, _end, m_author, DocTagType::Author, true);
else
// LTODO: Unknown tag, throw some form of warning and not just an exception
BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("@author tag in illegal comment"));
BOOST_THROW_EXCEPTION(Error(Error::Type::DocstringParsingError) << errinfo_comment("@author tag in illegal comment"));
case DocTagType::Title:
if (_owner == CommentOwner::Contract)
return parseDocTagLine(_pos, _end, m_title, DocTagType::Title, true);
else
// LTODO: Unknown tag, throw some form of warning and not just an exception
BOOST_THROW_EXCEPTION(DocstringParsingError() << errinfo_comment("@title tag in illegal comment"));
BOOST_THROW_EXCEPTION(Error(Error::Type::DocstringParsingError) << errinfo_comment("@title tag in illegal comment"));
case DocTagType::Param:
return appendDocTagParam(_pos, _end);
default:
@ -451,7 +451,7 @@ void InterfaceHandler::parseDocString(string const& _string, CommentOwner _owner
auto tagNameEndPos = firstSpaceOrNl(tagPos, end);
if (tagNameEndPos == end)
BOOST_THROW_EXCEPTION(
DocstringParsingError() <<
Error(Error::Type::DocstringParsingError) <<
errinfo_comment("End of tag " + string(tagPos, tagNameEndPos) + "not found"));
currPos = parseDocTag(tagNameEndPos + 1, end, string(tagPos + 1, tagNameEndPos), _owner);

View File

@ -33,8 +33,10 @@ namespace solidity
{
NameAndTypeResolver::NameAndTypeResolver(
vector<Declaration const*> const& _globals
)
vector<Declaration const*> const& _globals,
ErrorList& _errors
) :
m_errors(_errors)
{
for (Declaration const* declaration: _globals)
m_scopes[nullptr].registerDeclaration(*declaration);
@ -163,7 +165,7 @@ vector<Declaration const*> NameAndTypeResolver::cleanedDeclarations(
for (auto parameter: functionType.parameterTypes() + functionType.returnParameterTypes())
if (!parameter)
BOOST_THROW_EXCEPTION(
DeclarationError() <<
Error(Error::Type::DeclarationError) <<
errinfo_sourceLocation(_identifier.location()) <<
errinfo_comment("Function type can not be used in this context")
);
@ -408,7 +410,7 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
}
BOOST_THROW_EXCEPTION(
DeclarationError() <<
Error(Error::Type::DeclarationError) <<
errinfo_sourceLocation(secondDeclarationLocation) <<
errinfo_comment("Identifier already declared.") <<
errinfo_secondarySourceLocation(

View File

@ -42,7 +42,7 @@ namespace solidity
class NameAndTypeResolver: private boost::noncopyable
{
public:
NameAndTypeResolver(std::vector<Declaration const*> const& _globals);
NameAndTypeResolver(std::vector<Declaration const*> const& _globals, ErrorList& _errors);
/// Registers all declarations found in the source unit.
void registerDeclarations(SourceUnit& _sourceUnit);
/// Resolves all names and types referenced from the given contract.
@ -91,6 +91,7 @@ private:
std::map<ASTNode const*, DeclarationContainer> m_scopes;
DeclarationContainer* m_currentScope = nullptr;
ErrorList& m_errors;
};
/**

View File

@ -1156,9 +1156,9 @@ ASTPointer<ParameterList> Parser::createEmptyParameterList()
return nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>());
}
ParserError Parser::createParserError(string const& _description) const
Error Parser::createParserError(string const& _description) const
{
return ParserError() <<
return Error(Error::Type::ParserError) <<
errinfo_sourceLocation(SourceLocation(position(), position(), sourceName())) <<
errinfo_comment(_description);
}

View File

@ -147,7 +147,7 @@ private:
/// Creates a @ref ParserError exception and annotates it with the current position and the
/// given @a _description.
ParserError createParserError(std::string const& _description) const;
Error createParserError(std::string const& _description) const;
std::shared_ptr<Scanner> m_scanner;
/// Flag that signifies whether '_' is parsed as a PlaceholderStatement or a regular identifier.

View File

@ -67,6 +67,7 @@ TypePointer const& TypeChecker::type(VariableDeclaration const& _variable) const
bool TypeChecker::visit(ContractDefinition const& _contract)
{
// We force our own visiting order here.
ASTNode::listAccept(_contract.definedStructs(), *this);
ASTNode::listAccept(_contract.baseContracts(), *this);
@ -87,7 +88,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
{
if (fallbackFunction)
{
auto err = make_shared<DeclarationError>();
auto err = make_shared<Error>(Error::Type::DeclarationError);
*err << errinfo_comment("Only one fallback function is allowed.");
m_errors.push_back(err);
}
@ -143,7 +144,7 @@ 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<DeclarationError>();
auto err = make_shared<Error>(Error(Error::Type::DeclarationError));
*err <<
errinfo_sourceLocation(functions[_contract.name()].front()->location()) <<
errinfo_comment("More than one constructor defined.") <<
@ -157,7 +158,7 @@ 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<DeclarationError>();
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.") <<
@ -1251,7 +1252,7 @@ void TypeChecker::requireLValue(Expression const& _expression)
void TypeChecker::typeError(ASTNode const& _node, string const& _description)
{
auto err = make_shared<TypeError>();
auto err = make_shared<Error>(Error(Error::Type::TypeError));;
*err <<
errinfo_sourceLocation(_node.location()) <<
errinfo_comment(_description);

View File

@ -50,7 +50,7 @@ void StorageOffsets::computeOffsets(TypePointers const& _types)
byteOffset = 0;
}
if (slotOffset >= bigint(1) << 256)
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Object too large for storage."));
BOOST_THROW_EXCEPTION(Error(Error::Type::TypeError) << errinfo_comment("Object too large for storage."));
offsets[i] = make_pair(u256(slotOffset), byteOffset);
solAssert(type->storageSize() >= 1, "Invalid storage size.");
if (type->storageSize() == 1 && byteOffset + type->storageBytes() <= 32)
@ -64,7 +64,7 @@ void StorageOffsets::computeOffsets(TypePointers const& _types)
if (byteOffset > 0)
++slotOffset;
if (slotOffset >= bigint(1) << 256)
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Object too large for storage."));
BOOST_THROW_EXCEPTION(Error(Error::Type::TypeError) << errinfo_comment("Object too large for storage."));
m_storageSize = u256(slotOffset);
swap(m_offsets, offsets);
}
@ -805,7 +805,7 @@ u256 ArrayType::storageSize() const
else
size = bigint(length()) * baseType()->storageSize();
if (size >= bigint(1) << 256)
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Array too large for storage."));
BOOST_THROW_EXCEPTION(Error(Error::Type::TypeError) << errinfo_comment("Array too large for storage."));
return max<u256>(1, u256(size));
}

View File

@ -502,21 +502,6 @@ bool CommandLineInterface::processInput()
return false;
m_compiler->link(m_libraries);
}
catch (ParserError const& _exception)
{
SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Parser error", *m_compiler);
return false;
}
catch (DeclarationError const& _exception)
{
SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Declaration error", *m_compiler);
return false;
}
catch (TypeError const& _exception)
{
SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Type error", *m_compiler);
return false;
}
catch (CompilerError const& _exception)
{
SourceReferenceFormatter::printExceptionInformation(cerr, _exception, "Compiler error", *m_compiler);
@ -528,9 +513,13 @@ bool CommandLineInterface::processInput()
<< boost::diagnostic_information(_exception);
return false;
}
catch (DocstringParsingError const& _exception)
catch (Error const& _error)
{
cerr << "Documentation parsing error: " << *boost::get_error_info<errinfo_comment>(_exception) << endl;
if (_error.type() == Error::Type::DocstringParsingError)
cerr << "Documentation parsing error: " << *boost::get_error_info<errinfo_comment>(_error) << endl;
else
SourceReferenceFormatter::printExceptionInformation(cerr, _error, _error.typeName(), *m_compiler);
return false;
}
catch (Exception const& _exception)

View File

@ -134,17 +134,9 @@ string compile(string _input, bool _optimize)
));
success = succ; // keep success false on exception
}
catch (ParserError const& exception)
catch (Error const& error)
{
errors.append(formatError(exception, "Parser error", compiler));
}
catch (DeclarationError const& exception)
{
errors.append(formatError(exception, "Declaration error", compiler));
}
catch (TypeError const& exception)
{
errors.append(formatError(exception, "Type error", compiler));
errors.append(formatError(error, error.typeName(), compiler));
}
catch (CompilerError const& exception)
{
@ -154,10 +146,6 @@ string compile(string _input, bool _optimize)
{
errors.append(formatError(exception, "Internal compiler error", compiler));
}
catch (DocstringParsingError const& exception)
{
errors.append(formatError(exception, "Documentation parsing error", compiler));
}
catch (Exception const& exception)
{
errors.append("Exception during compilation: " + boost::diagnostic_information(exception));

View File

@ -85,9 +85,12 @@ Declaration const& resolveDeclaration(
return *declaration;
}
bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _functions = {},
vector<vector<string>> _localVariables = {},
vector<shared_ptr<MagicVariableDeclaration const>> _globalDeclarations = {})
bytes compileFirstExpression(
const string& _sourceCode,
vector<vector<string>> _functions = {},
vector<vector<string>> _localVariables = {},
vector<shared_ptr<MagicVariableDeclaration const>> _globalDeclarations = {}
)
{
Parser parser;
ASTPointer<SourceUnit> sourceUnit;
@ -105,7 +108,9 @@ bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _
declarations.reserve(_globalDeclarations.size() + 1);
for (ASTPointer<Declaration const> const& variable: _globalDeclarations)
declarations.push_back(variable.get());
NameAndTypeResolver resolver(declarations);
/// TODO:
ErrorList errorList;
NameAndTypeResolver resolver(declarations, errorList);
resolver.registerDeclarations(*sourceUnit);
vector<ContractDefinition const*> inheritanceHierarchy;

View File

@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration)
char const* text = "contract test {\n"
" uint256 ;\n"
"}\n";
BOOST_CHECK_THROW(parseText(text), ParserError);
BOOST_CHECK_THROW(parseText(text), Error);
}
BOOST_AUTO_TEST_CASE(empty_function)