diff options
-rw-r--r-- | libsolidity/AST.cpp | 4 | ||||
-rw-r--r-- | libsolidity/AST.h | 14 | ||||
-rw-r--r-- | libsolidity/CompilerStack.cpp | 4 | ||||
-rw-r--r-- | libsolidity/CompilerStack.h | 5 | ||||
-rw-r--r-- | libsolidity/Exceptions.h | 52 | ||||
-rw-r--r-- | libsolidity/InterfaceHandler.cpp | 16 | ||||
-rw-r--r-- | libsolidity/NameAndTypeResolver.cpp | 10 | ||||
-rw-r--r-- | libsolidity/NameAndTypeResolver.h | 3 | ||||
-rw-r--r-- | libsolidity/Parser.cpp | 4 | ||||
-rw-r--r-- | libsolidity/Parser.h | 2 | ||||
-rw-r--r-- | libsolidity/TypeChecker.cpp | 9 | ||||
-rw-r--r-- | libsolidity/Types.cpp | 6 | ||||
-rw-r--r-- | solc/CommandLineInterface.cpp | 23 | ||||
-rw-r--r-- | solc/jsonCompiler.cpp | 16 | ||||
-rw-r--r-- | test/libsolidity/SolidityExpressionCompiler.cpp | 13 | ||||
-rw-r--r-- | test/libsolidity/SolidityParser.cpp | 2 |
16 files changed, 107 insertions, 76 deletions
diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 490ae29a..f184e037 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -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 diff --git a/libsolidity/AST.h b/libsolidity/AST.h index f257dfb2..9dd67cc2 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -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; } diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 8c1cd8cf..519f785b 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -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.") ); diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index da26148d..5b128868 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -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; }; } diff --git a/libsolidity/Exceptions.h b/libsolidity/Exceptions.h index 8ab33999..723475c7 100644 --- a/libsolidity/Exceptions.h +++ b/libsolidity/Exceptions.h @@ -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>; diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index be15ae58..17ca66b4 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -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); diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 0d2c3b02..3591c07a 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -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( diff --git a/libsolidity/NameAndTypeResolver.h b/libsolidity/NameAndTypeResolver.h index f5f4c6ce..d5afb29a 100644 --- a/libsolidity/NameAndTypeResolver.h +++ b/libsolidity/NameAndTypeResolver.h @@ -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; }; /** diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 88a6b030..ce13098e 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -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); } diff --git a/libsolidity/Parser.h b/libsolidity/Parser.h index 043d022b..c9acb47d 100644 --- a/libsolidity/Parser.h +++ b/libsolidity/Parser.h @@ -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. diff --git a/libsolidity/TypeChecker.cpp b/libsolidity/TypeChecker.cpp index afffe344..658e4874 100644 --- a/libsolidity/TypeChecker.cpp +++ b/libsolidity/TypeChecker.cpp @@ -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); diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index c800e288..3ccaaf5d 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -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)); } diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index be10faa8..42b65d4c 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -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) diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index 00fd0370..1cf539e5 100644 --- a/solc/jsonCompiler.cpp +++ b/solc/jsonCompiler.cpp @@ -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)); diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 545775ee..8134080e 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -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; diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 03930479..a90399fc 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -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) |