From 87821c53c3a73d3e35a0e50a7c159d9aa5d6b253 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 14 Nov 2018 14:59:30 +0100 Subject: Isolating files shared between Yul- and Solidity language frontend. --- libevmasm/Assembly.h | 4 +- libevmasm/AssemblyItem.h | 2 +- libevmasm/ConstantOptimiser.h | 2 +- libevmasm/GasMeter.h | 2 +- libevmasm/PathGasMeter.h | 2 +- libevmasm/SourceLocation.h | 105 --- liblangutil/EVMVersion.h | 94 +++ liblangutil/ErrorReporter.cpp | 226 +++++ liblangutil/ErrorReporter.h | 126 +++ liblangutil/Exceptions.cpp | 66 ++ liblangutil/Exceptions.h | 132 +++ liblangutil/ParserBase.cpp | 115 +++ liblangutil/ParserBase.h | 93 +++ liblangutil/Scanner.cpp | 920 +++++++++++++++++++++ liblangutil/Scanner.h | 249 ++++++ liblangutil/SourceLocation.h | 105 +++ liblangutil/Token.cpp | 207 +++++ liblangutil/Token.h | 378 +++++++++ liblangutil/UndefMacros.h | 46 ++ liblll/Compiler.h | 2 +- libsolidity/CMakeLists.txt | 4 +- libsolidity/analysis/ConstantEvaluator.cpp | 2 +- libsolidity/analysis/ControlFlowGraph.h | 2 +- libsolidity/analysis/DocStringAnalyser.cpp | 2 +- libsolidity/analysis/NameAndTypeResolver.cpp | 2 +- libsolidity/analysis/PostTypeChecker.cpp | 2 +- libsolidity/analysis/ReferencesResolver.cpp | 4 +- libsolidity/analysis/SemVerHandler.h | 2 +- libsolidity/analysis/StaticAnalyzer.cpp | 2 +- libsolidity/analysis/SyntaxChecker.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/analysis/TypeChecker.h | 2 +- libsolidity/analysis/ViewPureChecker.h | 2 +- libsolidity/ast/AST.h | 4 +- libsolidity/ast/ASTEnums.h | 2 +- libsolidity/ast/ASTJsonConverter.h | 2 +- libsolidity/ast/Types.h | 4 +- libsolidity/codegen/ABIFunctions.h | 2 +- libsolidity/codegen/ArrayUtils.cpp | 2 +- libsolidity/codegen/Compiler.h | 2 +- libsolidity/codegen/CompilerContext.cpp | 4 +- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/codegen/ContractCompiler.cpp | 2 +- libsolidity/codegen/ExpressionCompiler.h | 4 +- libsolidity/codegen/LValue.h | 2 +- libsolidity/formal/CVC4Interface.cpp | 2 +- libsolidity/formal/SMTChecker.cpp | 2 +- libsolidity/formal/SMTChecker.h | 2 +- libsolidity/formal/SMTLib2Interface.cpp | 2 +- libsolidity/formal/SMTLib2Interface.h | 2 +- libsolidity/formal/SolverInterface.h | 2 +- libsolidity/formal/Z3Interface.cpp | 2 +- libsolidity/inlineasm/AsmAnalysis.cpp | 2 +- libsolidity/inlineasm/AsmAnalysis.h | 4 +- libsolidity/inlineasm/AsmCodeGen.cpp | 2 +- libsolidity/inlineasm/AsmData.h | 2 +- libsolidity/inlineasm/AsmParser.cpp | 4 +- libsolidity/inlineasm/AsmParser.h | 2 +- libsolidity/inlineasm/AsmPrinter.cpp | 2 +- libsolidity/inlineasm/AsmScope.h | 2 +- libsolidity/inlineasm/AsmScopeFiller.cpp | 4 +- libsolidity/interface/AssemblyStack.cpp | 2 +- libsolidity/interface/AssemblyStack.h | 4 +- libsolidity/interface/CompilerStack.cpp | 2 +- libsolidity/interface/CompilerStack.h | 6 +- libsolidity/interface/EVMVersion.h | 94 --- libsolidity/interface/ErrorReporter.cpp | 226 ----- libsolidity/interface/ErrorReporter.h | 126 --- libsolidity/interface/Exceptions.cpp | 66 -- libsolidity/interface/Exceptions.h | 132 --- libsolidity/interface/GasEstimator.h | 2 +- libsolidity/interface/SourceReferenceFormatter.cpp | 4 +- libsolidity/interface/SourceReferenceFormatter.h | 2 +- libsolidity/interface/Version.cpp | 2 +- libsolidity/parsing/DocStringParser.cpp | 4 +- libsolidity/parsing/Parser.cpp | 6 +- libsolidity/parsing/Parser.h | 2 +- libsolidity/parsing/ParserBase.cpp | 115 --- libsolidity/parsing/ParserBase.h | 93 --- libsolidity/parsing/Scanner.cpp | 920 --------------------- libsolidity/parsing/Scanner.h | 249 ------ libsolidity/parsing/Token.cpp | 207 ----- libsolidity/parsing/Token.h | 378 --------- libsolidity/parsing/UndefMacros.h | 46 -- libyul/backends/evm/EVMAssembly.cpp | 2 +- libyul/backends/evm/EVMCodeTransform.cpp | 2 +- libyul/optimiser/FullInliner.h | 2 +- solc/CommandLineInterface.cpp | 4 +- solc/CommandLineInterface.h | 2 +- test/CMakeLists.txt | 3 + test/ExecutionFramework.h | 2 +- test/Options.cpp | 4 +- test/Options.h | 2 +- test/RPCSession.cpp | 2 +- test/libevmasm/SourceLocation.cpp | 50 -- test/liblangutil/SourceLocation.cpp | 50 ++ test/libsolidity/ABIDecoderTests.cpp | 2 +- test/libsolidity/ABIEncoderTests.cpp | 2 +- test/libsolidity/AnalysisFramework.cpp | 2 +- test/libsolidity/Assembly.cpp | 6 +- test/libsolidity/ErrorCheck.h | 2 +- test/libsolidity/Imports.cpp | 2 +- test/libsolidity/InlineAssembly.cpp | 4 +- test/libsolidity/SemVerMatcher.cpp | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 4 +- test/libsolidity/SolidityExecutionFramework.h | 2 +- test/libsolidity/SolidityExpressionCompiler.cpp | 4 +- test/libsolidity/SolidityNatspecJSON.cpp | 2 +- test/libsolidity/SolidityParser.cpp | 4 +- test/libsolidity/SolidityScanner.cpp | 2 +- test/libsolidity/SyntaxTest.h | 2 +- test/libyul/Common.cpp | 4 +- test/libyul/Parser.cpp | 4 +- test/libyul/YulOptimizerTest.cpp | 4 +- test/tools/yulopti.cpp | 4 +- 115 files changed, 2925 insertions(+), 2922 deletions(-) delete mode 100644 libevmasm/SourceLocation.h create mode 100644 liblangutil/EVMVersion.h create mode 100644 liblangutil/ErrorReporter.cpp create mode 100644 liblangutil/ErrorReporter.h create mode 100644 liblangutil/Exceptions.cpp create mode 100644 liblangutil/Exceptions.h create mode 100644 liblangutil/ParserBase.cpp create mode 100644 liblangutil/ParserBase.h create mode 100644 liblangutil/Scanner.cpp create mode 100644 liblangutil/Scanner.h create mode 100644 liblangutil/SourceLocation.h create mode 100644 liblangutil/Token.cpp create mode 100644 liblangutil/Token.h create mode 100644 liblangutil/UndefMacros.h delete mode 100644 libsolidity/interface/EVMVersion.h delete mode 100644 libsolidity/interface/ErrorReporter.cpp delete mode 100644 libsolidity/interface/ErrorReporter.h delete mode 100644 libsolidity/interface/Exceptions.cpp delete mode 100644 libsolidity/interface/Exceptions.h delete mode 100644 libsolidity/parsing/ParserBase.cpp delete mode 100644 libsolidity/parsing/ParserBase.h delete mode 100644 libsolidity/parsing/Scanner.cpp delete mode 100644 libsolidity/parsing/Scanner.h delete mode 100644 libsolidity/parsing/Token.cpp delete mode 100644 libsolidity/parsing/Token.h delete mode 100644 libsolidity/parsing/UndefMacros.h delete mode 100644 test/libevmasm/SourceLocation.cpp create mode 100644 test/liblangutil/SourceLocation.cpp diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 8ef36923..e1993082 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -18,12 +18,12 @@ #pragma once #include -#include +#include #include #include #include -#include +#include #include #include diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 6187e18f..802bde25 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include "Exceptions.h" using namespace dev::solidity; diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index 2c2b87a0..04c43c5d 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index da90b028..e3909e86 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/libevmasm/PathGasMeter.h b/libevmasm/PathGasMeter.h index fb821684..772df484 100644 --- a/libevmasm/PathGasMeter.h +++ b/libevmasm/PathGasMeter.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include diff --git a/libevmasm/SourceLocation.h b/libevmasm/SourceLocation.h deleted file mode 100644 index b42c3aa9..00000000 --- a/libevmasm/SourceLocation.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - 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 . -*/ -/** - * @author Lefteris Karapetsas - * @date 2015 - * Represents a location in a source file - */ - -#pragma once - -#include -#include -#include -#include -#include // defines noexcept macro for MSVC - -namespace dev -{ - -/** - * Representation of an interval of source positions. - * The interval includes start and excludes end. - */ -struct SourceLocation -{ - SourceLocation(): start(-1), end(-1) { } - SourceLocation(int _start, int _end, std::shared_ptr _sourceName): - start(_start), end(_end), sourceName(_sourceName) { } - SourceLocation(SourceLocation&& _other) noexcept: - start(_other.start), - end(_other.end), - sourceName(std::move(_other.sourceName)) - {} - SourceLocation(SourceLocation const&) = default; - SourceLocation& operator=(SourceLocation const&) = default; - SourceLocation& operator=(SourceLocation&& _other) noexcept - { - start = _other.start; - end = _other.end; - sourceName = std::move(_other.sourceName); - return *this; - } - - bool operator==(SourceLocation const& _other) const - { - return start == _other.start && end == _other.end && - ((!sourceName && !_other.sourceName) || (sourceName && _other.sourceName && *sourceName == *_other.sourceName)); - } - bool operator!=(SourceLocation const& _other) const { return !operator==(_other); } - inline bool operator<(SourceLocation const& _other) const; - inline bool contains(SourceLocation const& _other) const; - inline bool intersects(SourceLocation const& _other) const; - - bool isEmpty() const { return start == -1 && end == -1; } - - int start; - int end; - std::shared_ptr sourceName; -}; - -/// Stream output for Location (used e.g. in boost exceptions). -inline std::ostream& operator<<(std::ostream& _out, SourceLocation const& _location) -{ - if (_location.isEmpty()) - return _out << "NO_LOCATION_SPECIFIED"; - return _out << *_location.sourceName << "[" << _location.start << "," << _location.end << ")"; -} - -bool SourceLocation::operator<(SourceLocation const& _other) const -{ - if (!sourceName || !_other.sourceName) - return std::make_tuple(int(!!sourceName), start, end) < std::make_tuple(int(!!_other.sourceName), _other.start, _other.end); - else - return std::make_tuple(*sourceName, start, end) < std::make_tuple(*_other.sourceName, _other.start, _other.end); -} - -bool SourceLocation::contains(SourceLocation const& _other) const -{ - if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName))) - return false; - return start <= _other.start && _other.end <= end; -} - -bool SourceLocation::intersects(SourceLocation const& _other) const -{ - if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName))) - return false; - return _other.start < end && start < _other.end; -} - -} diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h new file mode 100644 index 00000000..657727ac --- /dev/null +++ b/liblangutil/EVMVersion.h @@ -0,0 +1,94 @@ +/* + 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 . +*/ +/** + * EVM versioning. + */ + +#pragma once + +#include + +#include +#include + +namespace dev +{ +namespace solidity +{ + +/** + * A version specifier of the EVM we want to compile to. + * Defaults to the latest version. + */ +class EVMVersion: + boost::less_than_comparable, + boost::equality_comparable +{ +public: + EVMVersion() {} + + static EVMVersion homestead() { return {Version::Homestead}; } + static EVMVersion tangerineWhistle() { return {Version::TangerineWhistle}; } + static EVMVersion spuriousDragon() { return {Version::SpuriousDragon}; } + static EVMVersion byzantium() { return {Version::Byzantium}; } + static EVMVersion constantinople() { return {Version::Constantinople}; } + + static boost::optional fromString(std::string const& _version) + { + for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople()}) + if (_version == v.name()) + return v; + return {}; + } + + bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; } + bool operator<(EVMVersion const& _other) const { return m_version < _other.m_version; } + + std::string name() const + { + switch (m_version) + { + case Version::Homestead: return "homestead"; + case Version::TangerineWhistle: return "tangerineWhistle"; + case Version::SpuriousDragon: return "spuriousDragon"; + case Version::Byzantium: return "byzantium"; + case Version::Constantinople: return "constantinople"; + } + return "INVALID"; + } + + /// Has the RETURNDATACOPY and RETURNDATASIZE opcodes. + bool supportsReturndata() const { return *this >= byzantium(); } + bool hasStaticCall() const { return *this >= byzantium(); } + bool hasBitwiseShifting() const { return *this >= constantinople(); } + bool hasCreate2() const { return *this >= constantinople(); } + + /// Whether we have to retain the costs for the call opcode itself (false), + /// or whether we can just forward easily all remaining gas (true). + bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); } + +private: + enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople }; + + EVMVersion(Version _version): m_version(_version) {} + + Version m_version = Version::Byzantium; +}; + + +} +} diff --git a/liblangutil/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp new file mode 100644 index 00000000..5edb0eeb --- /dev/null +++ b/liblangutil/ErrorReporter.cpp @@ -0,0 +1,226 @@ +/* + 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 . +*/ +/** + * @author Rhett + * @date 2017 + * Error helper class. + */ + +#include +#include +#include + +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::warning( + SourceLocation const& _location, + string const& _description, + SecondarySourceLocation const& _secondaryLocation +) +{ + error(Error::Type::Warning, _location, _secondaryLocation, _description); +} + +void ErrorReporter::error(Error::Type _type, SourceLocation const& _location, string const& _description) +{ + if (checkForExcessiveErrors(_type)) + return; + + auto err = make_shared(_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) +{ + if (checkForExcessiveErrors(_type)) + return; + + auto err = make_shared(_type); + *err << + errinfo_sourceLocation(_location) << + errinfo_secondarySourceLocation(_secondaryLocation) << + errinfo_comment(_description); + + m_errorList.push_back(err); +} + +bool ErrorReporter::checkForExcessiveErrors(Error::Type _type) +{ + if (_type == Error::Type::Warning) + { + m_warningCount++; + + if (m_warningCount == c_maxWarningsAllowed) + { + auto err = make_shared(Error::Type::Warning); + *err << errinfo_comment("There are more than 256 warnings. Ignoring the rest."); + m_errorList.push_back(err); + } + + if (m_warningCount >= c_maxWarningsAllowed) + return true; + } + else + { + m_errorCount++; + + if (m_errorCount > c_maxErrorsAllowed) + { + auto err = make_shared(Error::Type::Warning); + *err << errinfo_comment("There are more than 256 errors. Aborting."); + m_errorList.push_back(err); + BOOST_THROW_EXCEPTION(FatalError()); + } + } + + return false; +} + +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, SecondarySourceLocation const& _secondaryLocation, string const& _description) +{ + error( + Error::Type::TypeError, + _location, + _secondaryLocation, + _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 + ); +} diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h new file mode 100644 index 00000000..72cf16a4 --- /dev/null +++ b/liblangutil/ErrorReporter.h @@ -0,0 +1,126 @@ +/* + 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 . +*/ +/** + * @author Rhett + * @date 2017 + * Error reporting helper class. + */ + +#pragma once + +#include +#include + +namespace dev +{ +namespace solidity +{ + +class ASTNode; + +class ErrorReporter +{ +public: + + explicit ErrorReporter(ErrorList& _errors): + m_errorList(_errors) { } + + ErrorReporter(ErrorReporter const& _errorReporter) noexcept: + m_errorList(_errorReporter.m_errorList) { } + + ErrorReporter& operator=(ErrorReporter const& _errorReporter); + + void warning(std::string const& _description); + + void warning(SourceLocation const& _location, std::string const& _description); + + void warning( + SourceLocation const& _location, + std::string const& _description, + SecondarySourceLocation const& _secondaryLocation + ); + + void error( + Error::Type _type, + SourceLocation const& _location, + std::string const& _description + ); + + void declarationError( + SourceLocation const& _location, + SecondarySourceLocation const& _secondaryLocation, + std::string const& _description + ); + + void declarationError(SourceLocation const& _location, std::string const& _description); + + 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, + SecondarySourceLocation const& _secondaryLocation = SecondarySourceLocation(), + std::string const& _description = std::string() + ); + + void typeError(SourceLocation const& _location, std::string const& _description); + + void fatalTypeError(SourceLocation const& _location, std::string const& _description); + + void docstringParsingError(std::string const& _description); + + ErrorList const& errors() const; + + void clear(); + + /// @returns true iff there is any error (ignores warnings). + bool hasErrors() const + { + return m_errorCount > 0; + } + +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()); + + // @returns true if error shouldn't be stored + bool checkForExcessiveErrors(Error::Type _type); + + ErrorList& m_errorList; + + unsigned m_errorCount = 0; + unsigned m_warningCount = 0; + + const unsigned c_maxWarningsAllowed = 256; + const unsigned c_maxErrorsAllowed = 256; +}; + + +} +} + diff --git a/liblangutil/Exceptions.cpp b/liblangutil/Exceptions.cpp new file mode 100644 index 00000000..069619dd --- /dev/null +++ b/liblangutil/Exceptions.cpp @@ -0,0 +1,66 @@ +/* + 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 . +*/ +/** + * @author Liana + * @date 2015 + * Solidity exception hierarchy. + */ + +#include + +using namespace std; +using namespace dev; +using namespace dev::solidity; + +Error::Error(Type _type, SourceLocation const& _location, string const& _description): + m_type(_type) +{ + switch(m_type) + { + case Type::DeclarationError: + m_typeName = "DeclarationError"; + break; + case Type::DocstringParsingError: + m_typeName = "DocstringParsingError"; + break; + case Type::ParserError: + m_typeName = "ParserError"; + break; + case Type::SyntaxError: + m_typeName = "SyntaxError"; + break; + case Type::TypeError: + m_typeName = "TypeError"; + break; + case Type::Warning: + m_typeName = "Warning"; + break; + } + + if (!_location.isEmpty()) + *this << errinfo_sourceLocation(_location); + if (!_description.empty()) + *this << errinfo_comment(_description); +} + +Error::Error(Error::Type _type, const std::string& _description, const SourceLocation& _location): + Error(_type) +{ + if (!_location.isEmpty()) + *this << errinfo_sourceLocation(_location); + *this << errinfo_comment(_description); +} diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h new file mode 100644 index 00000000..69efd6dd --- /dev/null +++ b/liblangutil/Exceptions.h @@ -0,0 +1,132 @@ +/* + 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 . +*/ +/** + * @author Christian + * @date 2014 + * Solidity exception hierarchy. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace dev +{ +namespace solidity +{ +class Error; +using ErrorList = std::vector>; + +struct CompilerError: virtual Exception {}; +struct InternalCompilerError: virtual Exception {}; +struct FatalError: virtual Exception {}; +struct UnimplementedFeatureError: virtual Exception{}; + +/// Assertion that throws an InternalCompilerError containing the given description if it is not met. +#define solAssert(CONDITION, DESCRIPTION) \ + assertThrow(CONDITION, ::dev::solidity::InternalCompilerError, DESCRIPTION) + +#define solUnimplementedAssert(CONDITION, DESCRIPTION) \ + assertThrow(CONDITION, ::dev::solidity::UnimplementedFeatureError, DESCRIPTION) + +#define solUnimplemented(DESCRIPTION) \ + solUnimplementedAssert(false, DESCRIPTION) + +class Error: virtual public Exception +{ +public: + enum class Type + { + DeclarationError, + DocstringParsingError, + ParserError, + TypeError, + SyntaxError, + Warning + }; + + explicit Error( + Type _type, + SourceLocation const& _location = SourceLocation(), + std::string const& _description = std::string() + ); + + Error(Type _type, std::string const& _description, SourceLocation const& _location = SourceLocation()); + + Type type() const { return m_type; } + std::string const& typeName() const { return m_typeName; } + + /// helper functions + static Error const* containsErrorOfType(ErrorList const& _list, Error::Type _type) + { + for (auto e: _list) + { + if (e->type() == _type) + return e.get(); + } + return nullptr; + } + static bool containsOnlyWarnings(ErrorList const& _list) + { + for (auto e: _list) + { + if (e->type() != Type::Warning) + return false; + } + return true; + } +private: + Type m_type; + std::string m_typeName; +}; + + +using errorSourceLocationInfo = std::pair; + +class SecondarySourceLocation +{ +public: + SecondarySourceLocation& append(std::string const& _errMsg, SourceLocation const& _sourceLocation) + { + infos.push_back(std::make_pair(_errMsg, _sourceLocation)); + return *this; + } + /// Limits the number of secondary source locations to 32 and appends a notice to the + /// error message. + void limitSize(std::string& _message) + { + size_t occurrences = infos.size(); + if (occurrences > 32) + { + infos.resize(32); + _message += " Truncated from " + std::to_string(occurrences) + " to the first 32 occurrences."; + } + } + + std::vector infos; +}; + + +using errinfo_sourceLocation = boost::error_info; +using errinfo_secondarySourceLocation = boost::error_info; + +} +} diff --git a/liblangutil/ParserBase.cpp b/liblangutil/ParserBase.cpp new file mode 100644 index 00000000..197c2d65 --- /dev/null +++ b/liblangutil/ParserBase.cpp @@ -0,0 +1,115 @@ +/* + 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 . +*/ +/** + * @author Christian + * @date 2016 + * Solidity parser shared functionality. + */ + +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::solidity; + +std::shared_ptr const& ParserBase::sourceName() const +{ + return m_scanner->sourceName(); +} + +int ParserBase::position() const +{ + return m_scanner->currentLocation().start; +} + +int ParserBase::endPosition() const +{ + return m_scanner->currentLocation().end; +} + +Token ParserBase::currentToken() const +{ + return m_scanner->currentToken(); +} + +Token ParserBase::peekNextToken() const +{ + return m_scanner->peekNextToken(); +} + +std::string ParserBase::currentLiteral() const +{ + return m_scanner->currentLiteral(); +} + +Token ParserBase::advance() +{ + return m_scanner->next(); +} + +void ParserBase::expectToken(Token _value, bool _advance) +{ + Token tok = m_scanner->currentToken(); + if (tok != _value) + { + auto tokenName = [this](Token _token) + { + if (_token == Token::Identifier) + return string("identifier"); + else if (_token == Token::EOS) + return string("end of source"); + else if (TokenTraits::isReservedKeyword(_token)) + return string("reserved keyword '") + TokenTraits::friendlyName(_token) + "'"; + else if (TokenTraits::isElementaryTypeName(_token)) //for the sake of accuracy in reporting + { + ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken(); + return string("'") + elemTypeName.toString() + "'"; + } + else + return string("'") + TokenTraits::friendlyName(_token) + "'"; + }; + + fatalParserError(string("Expected ") + tokenName(_value) + string(" but got ") + tokenName(tok)); + } + if (_advance) + m_scanner->next(); +} + +void ParserBase::increaseRecursionDepth() +{ + m_recursionDepth++; + if (m_recursionDepth >= 2560) + fatalParserError("Maximum recursion depth reached during parsing."); +} + +void ParserBase::decreaseRecursionDepth() +{ + solAssert(m_recursionDepth > 0, ""); + m_recursionDepth--; +} + +void ParserBase::parserError(string const& _description) +{ + m_errorReporter.parserError(SourceLocation(position(), endPosition(), sourceName()), _description); +} + +void ParserBase::fatalParserError(string const& _description) +{ + m_errorReporter.fatalParserError(SourceLocation(position(), endPosition(), sourceName()), _description); +} diff --git a/liblangutil/ParserBase.h b/liblangutil/ParserBase.h new file mode 100644 index 00000000..0cd94eee --- /dev/null +++ b/liblangutil/ParserBase.h @@ -0,0 +1,93 @@ +/* + 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 . +*/ +/** + * @author Christian + * @date 2016 + * Solidity parser shared functionality. + */ + +#pragma once + +#include +#include + +namespace dev +{ +namespace solidity +{ + +class ErrorReporter; +class Scanner; + +class ParserBase +{ +public: + explicit ParserBase(ErrorReporter& errorReporter): m_errorReporter(errorReporter) {} + + std::shared_ptr const& sourceName() const; + +protected: + /// Utility class that creates an error and throws an exception if the + /// recursion depth is too deep. + class RecursionGuard + { + public: + explicit RecursionGuard(ParserBase& _parser): m_parser(_parser) + { + m_parser.increaseRecursionDepth(); + } + ~RecursionGuard() { m_parser.decreaseRecursionDepth(); } + private: + ParserBase& m_parser; + }; + + /// Start position of the current token + int position() const; + /// End position of the current token + int endPosition() const; + + ///@{ + ///@name Helper functions + /// If current token value is not _value, throw exception otherwise advance token. + void expectToken(Token _value, bool _advance = true); + Token currentToken() const; + Token peekNextToken() const; + std::string currentLiteral() const; + Token advance(); + ///@} + + /// Increases the recursion depth and throws an exception if it is too deep. + void increaseRecursionDepth(); + void decreaseRecursionDepth(); + + /// Creates a @ref ParserError and annotates it with the current position and the + /// given @a _description. + void parserError(std::string const& _description); + + /// Creates a @ref ParserError and annotates it with the current position and the + /// given @a _description. Throws the FatalError. + void fatalParserError(std::string const& _description); + + std::shared_ptr m_scanner; + /// The reference to the list of errors and warning to add errors/warnings during parsing + ErrorReporter& m_errorReporter; + /// Current recursion depth during parsing. + size_t m_recursionDepth = 0; +}; + +} +} diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp new file mode 100644 index 00000000..246f5ea6 --- /dev/null +++ b/liblangutil/Scanner.cpp @@ -0,0 +1,920 @@ +/* + 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 . + + This file is derived from the file "scanner.cc", which was part of the + V8 project. The original copyright header follows: + + Copyright 2006-2012, the V8 project authors. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/** + * @author Christian + * @date 2014 + * Solidity scanner. + */ + +#include +#include +#include +#include + +using namespace std; + +namespace dev +{ +namespace solidity +{ + +namespace +{ +bool isDecimalDigit(char c) +{ + return '0' <= c && c <= '9'; +} +bool isHexDigit(char c) +{ + return isDecimalDigit(c) + || ('a' <= c && c <= 'f') + || ('A' <= c && c <= 'F'); +} +bool isLineTerminator(char c) +{ + return c == '\n'; +} +bool isWhiteSpace(char c) +{ + return c == ' ' || c == '\n' || c == '\t' || c == '\r'; +} +bool isIdentifierStart(char c) +{ + return c == '_' || c == '$' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); +} +bool isIdentifierPart(char c) +{ + return isIdentifierStart(c) || isDecimalDigit(c); +} +int hexValue(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else return -1; +} +} // end anonymous namespace + + + +/// Scoped helper for literal recording. Automatically drops the literal +/// if aborting the scanning before it's complete. +enum LiteralType { + LITERAL_TYPE_STRING, + LITERAL_TYPE_NUMBER, // not really different from string type in behaviour + LITERAL_TYPE_COMMENT +}; + +class LiteralScope +{ +public: + explicit LiteralScope(Scanner* _self, enum LiteralType _type): m_type(_type) + , m_scanner(_self) + , m_complete(false) + { + if (_type == LITERAL_TYPE_COMMENT) + m_scanner->m_nextSkippedComment.literal.clear(); + else + m_scanner->m_nextToken.literal.clear(); + } + ~LiteralScope() + { + if (!m_complete) + { + if (m_type == LITERAL_TYPE_COMMENT) + m_scanner->m_nextSkippedComment.literal.clear(); + else + m_scanner->m_nextToken.literal.clear(); + } + } + void complete() { m_complete = true; } + +private: + enum LiteralType m_type; + Scanner* m_scanner; + bool m_complete; +}; // end of LiteralScope class + + +void Scanner::reset(CharStream const& _source, string const& _sourceName) +{ + m_source = _source; + m_sourceName = make_shared(_sourceName); + reset(); +} + +void Scanner::reset() +{ + m_source.reset(); + m_char = m_source.get(); + skipWhitespace(); + scanToken(); + next(); +} + +bool Scanner::scanHexByte(char& o_scannedByte) +{ + char x = 0; + for (int i = 0; i < 2; i++) + { + int d = hexValue(m_char); + if (d < 0) + { + rollback(i); + return false; + } + x = x * 16 + d; + advance(); + } + o_scannedByte = x; + return true; +} + +bool Scanner::scanUnicode(unsigned & o_codepoint) +{ + unsigned x = 0; + for (int i = 0; i < 4; i++) + { + int d = hexValue(m_char); + if (d < 0) + { + rollback(i); + return false; + } + x = x * 16 + d; + advance(); + } + o_codepoint = x; + return true; +} + +// This supports codepoints between 0000 and FFFF. +void Scanner::addUnicodeAsUTF8(unsigned codepoint) +{ + if (codepoint <= 0x7f) + addLiteralChar(codepoint); + else if (codepoint <= 0x7ff) + { + addLiteralChar(0xc0 | (codepoint >> 6)); + addLiteralChar(0x80 | (codepoint & 0x3f)); + } + else + { + addLiteralChar(0xe0 | (codepoint >> 12)); + addLiteralChar(0x80 | ((codepoint >> 6) & 0x3f)); + addLiteralChar(0x80 | (codepoint & 0x3f)); + } +} + +// Ensure that tokens can be stored in a byte. +BOOST_STATIC_ASSERT(TokenTraits::count() <= 0x100); + +Token Scanner::next() +{ + m_currentToken = m_nextToken; + m_skippedComment = m_nextSkippedComment; + scanToken(); + + return m_currentToken.token; +} + +Token Scanner::selectToken(char _next, Token _then, Token _else) +{ + advance(); + if (m_char == _next) + return selectToken(_then); + else + return _else; +} + +bool Scanner::skipWhitespace() +{ + int const startPosition = sourcePos(); + while (isWhiteSpace(m_char)) + advance(); + // Return whether or not we skipped any characters. + return sourcePos() != startPosition; +} + +void Scanner::skipWhitespaceExceptUnicodeLinebreak() +{ + while (isWhiteSpace(m_char) && !isUnicodeLinebreak()) + advance(); +} + +Token Scanner::skipSingleLineComment() +{ + // Line terminator is not part of the comment. If it is a + // non-ascii line terminator, it will result in a parser error. + while (!isUnicodeLinebreak()) + if (!advance()) break; + + return Token::Whitespace; +} + +Token Scanner::scanSingleLineDocComment() +{ + LiteralScope literal(this, LITERAL_TYPE_COMMENT); + advance(); //consume the last '/' at /// + + skipWhitespaceExceptUnicodeLinebreak(); + + while (!isSourcePastEndOfInput()) + { + if (isLineTerminator(m_char)) + { + // check if next line is also a documentation comment + skipWhitespace(); + if (!m_source.isPastEndOfInput(3) && + m_source.get(0) == '/' && + m_source.get(1) == '/' && + m_source.get(2) == '/') + { + addCommentLiteralChar('\n'); + m_char = m_source.advanceAndGet(3); + } + else + break; // next line is not a documentation comment, we are done + + } + else if (isUnicodeLinebreak()) + // Any line terminator that is not '\n' is considered to end the + // comment. + break; + addCommentLiteralChar(m_char); + advance(); + } + literal.complete(); + return Token::CommentLiteral; +} + +Token Scanner::skipMultiLineComment() +{ + advance(); + while (!isSourcePastEndOfInput()) + { + char ch = m_char; + advance(); + + // If we have reached the end of the multi-line comment, we + // consume the '/' and insert a whitespace. This way all + // multi-line comments are treated as whitespace. + if (ch == '*' && m_char == '/') + { + m_char = ' '; + return Token::Whitespace; + } + } + // Unterminated multi-line comment. + return Token::Illegal; +} + +Token Scanner::scanMultiLineDocComment() +{ + LiteralScope literal(this, LITERAL_TYPE_COMMENT); + bool endFound = false; + bool charsAdded = false; + + while (isWhiteSpace(m_char) && !isLineTerminator(m_char)) + advance(); + + while (!isSourcePastEndOfInput()) + { + //handle newlines in multline comments + if (isLineTerminator(m_char)) + { + skipWhitespace(); + if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '*') + { // it is unknown if this leads to the end of the comment + addCommentLiteralChar('*'); + advance(); + } + else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) != '/') + { // skip first '*' in subsequent lines + if (charsAdded) + addCommentLiteralChar('\n'); + m_char = m_source.advanceAndGet(2); + } + else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/') + { // if after newline the comment ends, don't insert the newline + m_char = m_source.advanceAndGet(2); + endFound = true; + break; + } + else if (charsAdded) + addCommentLiteralChar('\n'); + } + + if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/') + { + m_char = m_source.advanceAndGet(2); + endFound = true; + break; + } + addCommentLiteralChar(m_char); + charsAdded = true; + advance(); + } + literal.complete(); + if (!endFound) + return Token::Illegal; + else + return Token::CommentLiteral; +} + +Token Scanner::scanSlash() +{ + int firstSlashPosition = sourcePos(); + advance(); + if (m_char == '/') + { + if (!advance()) /* double slash comment directly before EOS */ + return Token::Whitespace; + else if (m_char == '/') + { + // doxygen style /// comment + Token comment; + m_nextSkippedComment.location.start = firstSlashPosition; + comment = scanSingleLineDocComment(); + m_nextSkippedComment.location.end = sourcePos(); + m_nextSkippedComment.token = comment; + return Token::Whitespace; + } + else + return skipSingleLineComment(); + } + else if (m_char == '*') + { + // doxygen style /** natspec comment + if (!advance()) /* slash star comment before EOS */ + return Token::Illegal; + else if (m_char == '*') + { + advance(); //consume the last '*' at /** + + // "/**/" + if (m_char == '/') + { + advance(); //skip the closing slash + return Token::Whitespace; + } + // we actually have a multiline documentation comment + Token comment; + m_nextSkippedComment.location.start = firstSlashPosition; + comment = scanMultiLineDocComment(); + m_nextSkippedComment.location.end = sourcePos(); + m_nextSkippedComment.token = comment; + if (comment == Token::Illegal) + return Token::Illegal; + else + return Token::Whitespace; + } + else + return skipMultiLineComment(); + } + else if (m_char == '=') + return selectToken(Token::AssignDiv); + else + return Token::Div; +} + +void Scanner::scanToken() +{ + m_nextToken.literal.clear(); + m_nextToken.extendedTokenInfo = make_tuple(0, 0); + m_nextSkippedComment.literal.clear(); + m_nextSkippedComment.extendedTokenInfo = make_tuple(0, 0); + + Token token; + // M and N are for the purposes of grabbing different type sizes + unsigned m; + unsigned n; + do + { + // Remember the position of the next token + m_nextToken.location.start = sourcePos(); + switch (m_char) + { + case '"': + case '\'': + token = scanString(); + break; + case '<': + // < <= << <<= + advance(); + if (m_char == '=') + token = selectToken(Token::LessThanOrEqual); + else if (m_char == '<') + token = selectToken('=', Token::AssignShl, Token::SHL); + else + token = Token::LessThan; + break; + case '>': + // > >= >> >>= >>> >>>= + advance(); + if (m_char == '=') + token = selectToken(Token::GreaterThanOrEqual); + else if (m_char == '>') + { + // >> >>= >>> >>>= + advance(); + if (m_char == '=') + token = selectToken(Token::AssignSar); + else if (m_char == '>') + token = selectToken('=', Token::AssignShr, Token::SHR); + else + token = Token::SAR; + } + else + token = Token::GreaterThan; + break; + case '=': + // = == => + advance(); + if (m_char == '=') + token = selectToken(Token::Equal); + else if (m_char == '>') + token = selectToken(Token::Arrow); + else + token = Token::Assign; + break; + case '!': + // ! != + advance(); + if (m_char == '=') + token = selectToken(Token::NotEqual); + else + token = Token::Not; + break; + case '+': + // + ++ += + advance(); + if (m_char == '+') + token = selectToken(Token::Inc); + else if (m_char == '=') + token = selectToken(Token::AssignAdd); + else + token = Token::Add; + break; + case '-': + // - -- -= + advance(); + if (m_char == '-') + token = selectToken(Token::Dec); + else if (m_char == '=') + token = selectToken(Token::AssignSub); + else + token = Token::Sub; + break; + case '*': + // * ** *= + advance(); + if (m_char == '*') + token = selectToken(Token::Exp); + else if (m_char == '=') + token = selectToken(Token::AssignMul); + else + token = Token::Mul; + break; + case '%': + // % %= + token = selectToken('=', Token::AssignMod, Token::Mod); + break; + case '/': + // / // /* /= + token = scanSlash(); + break; + case '&': + // & && &= + advance(); + if (m_char == '&') + token = selectToken(Token::And); + else if (m_char == '=') + token = selectToken(Token::AssignBitAnd); + else + token = Token::BitAnd; + break; + case '|': + // | || |= + advance(); + if (m_char == '|') + token = selectToken(Token::Or); + else if (m_char == '=') + token = selectToken(Token::AssignBitOr); + else + token = Token::BitOr; + break; + case '^': + // ^ ^= + token = selectToken('=', Token::AssignBitXor, Token::BitXor); + break; + case '.': + // . Number + advance(); + if (isDecimalDigit(m_char)) + token = scanNumber('.'); + else + token = Token::Period; + break; + case ':': + token = selectToken(Token::Colon); + break; + case ';': + token = selectToken(Token::Semicolon); + break; + case ',': + token = selectToken(Token::Comma); + break; + case '(': + token = selectToken(Token::LParen); + break; + case ')': + token = selectToken(Token::RParen); + break; + case '[': + token = selectToken(Token::LBrack); + break; + case ']': + token = selectToken(Token::RBrack); + break; + case '{': + token = selectToken(Token::LBrace); + break; + case '}': + token = selectToken(Token::RBrace); + break; + case '?': + token = selectToken(Token::Conditional); + break; + case '~': + token = selectToken(Token::BitNot); + break; + default: + if (isIdentifierStart(m_char)) + { + tie(token, m, n) = scanIdentifierOrKeyword(); + + // Special case for hexadecimal literals + if (token == Token::Hex) + { + // reset + m = 0; + n = 0; + + // Special quoted hex string must follow + if (m_char == '"' || m_char == '\'') + token = scanHexString(); + else + token = Token::IllegalHex; + } + } + else if (isDecimalDigit(m_char)) + token = scanNumber(); + else if (skipWhitespace()) + token = Token::Whitespace; + else if (isSourcePastEndOfInput()) + token = Token::EOS; + else + token = selectToken(Token::Illegal); + break; + } + // Continue scanning for tokens as long as we're just skipping + // whitespace. + } + while (token == Token::Whitespace); + m_nextToken.location.end = sourcePos(); + m_nextToken.token = token; + m_nextToken.extendedTokenInfo = make_tuple(m, n); +} + +bool Scanner::scanEscape() +{ + char c = m_char; + advance(); + // Skip escaped newlines. + if (isLineTerminator(c)) + return true; + switch (c) + { + case '\'': // fall through + case '"': // fall through + case '\\': + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = '\v'; + break; + case 'u': + { + unsigned codepoint; + if (!scanUnicode(codepoint)) + return false; + addUnicodeAsUTF8(codepoint); + return true; + } + case 'x': + if (!scanHexByte(c)) + return false; + break; + default: + return false; + } + + addLiteralChar(c); + return true; +} + +bool Scanner::isUnicodeLinebreak() +{ + if (0x0a <= m_char && m_char <= 0x0d) + // line feed, vertical tab, form feed, carriage return + return true; + else if (!m_source.isPastEndOfInput(1) && uint8_t(m_source.get(0)) == 0xc2 && uint8_t(m_source.get(1)) == 0x85) + // NEL - U+0085, C2 85 in utf8 + return true; + else if (!m_source.isPastEndOfInput(2) && uint8_t(m_source.get(0)) == 0xe2 && uint8_t(m_source.get(1)) == 0x80 && ( + uint8_t(m_source.get(2)) == 0xa8 || uint8_t(m_source.get(2)) == 0xa9 + )) + // LS - U+2028, E2 80 A8 in utf8 + // PS - U+2029, E2 80 A9 in utf8 + return true; + else + return false; +} + +Token Scanner::scanString() +{ + char const quote = m_char; + advance(); // consume quote + LiteralScope literal(this, LITERAL_TYPE_STRING); + while (m_char != quote && !isSourcePastEndOfInput() && !isUnicodeLinebreak()) + { + char c = m_char; + advance(); + if (c == '\\') + { + if (isSourcePastEndOfInput() || !scanEscape()) + return Token::Illegal; + } + else + addLiteralChar(c); + } + if (m_char != quote) + return Token::Illegal; + literal.complete(); + advance(); // consume quote + return Token::StringLiteral; +} + +Token Scanner::scanHexString() +{ + char const quote = m_char; + advance(); // consume quote + LiteralScope literal(this, LITERAL_TYPE_STRING); + while (m_char != quote && !isSourcePastEndOfInput()) + { + char c = m_char; + if (!scanHexByte(c)) + return Token::IllegalHex; + addLiteralChar(c); + } + if (m_char != quote) + return Token::IllegalHex; + literal.complete(); + advance(); // consume quote + return Token::StringLiteral; +} + +// Parse for regex [:digit:]+(_[:digit:]+)* +void Scanner::scanDecimalDigits() +{ + // MUST begin with a decimal digit. + if (!isDecimalDigit(m_char)) + return; + + // May continue with decimal digit or underscore for grouping. + do addLiteralCharAndAdvance(); + while (!m_source.isPastEndOfInput() && (isDecimalDigit(m_char) || m_char == '_')); + + // Defer further validation of underscore to SyntaxChecker. +} + +Token Scanner::scanNumber(char _charSeen) +{ + enum { DECIMAL, HEX, BINARY } kind = DECIMAL; + LiteralScope literal(this, LITERAL_TYPE_NUMBER); + if (_charSeen == '.') + { + // we have already seen a decimal point of the float + addLiteralChar('.'); + if (m_char == '_') + return Token::Illegal; + scanDecimalDigits(); // we know we have at least one digit + } + else + { + solAssert(_charSeen == 0, ""); + // if the first character is '0' we must check for octals and hex + if (m_char == '0') + { + addLiteralCharAndAdvance(); + // either 0, 0exxx, 0Exxx, 0.xxx or a hex number + if (m_char == 'x') + { + // hex number + kind = HEX; + addLiteralCharAndAdvance(); + if (!isHexDigit(m_char)) + return Token::Illegal; // we must have at least one hex digit after 'x' + + while (isHexDigit(m_char) || m_char == '_') // We keep the underscores for later validation + addLiteralCharAndAdvance(); + } + else if (isDecimalDigit(m_char)) + // We do not allow octal numbers + return Token::Illegal; + } + // Parse decimal digits and allow trailing fractional part. + if (kind == DECIMAL) + { + scanDecimalDigits(); // optional + if (m_char == '.') + { + if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_') + { + // Assume the input may be a floating point number with leading '_' in fraction part. + // Recover by consuming it all but returning `Illegal` right away. + addLiteralCharAndAdvance(); // '.' + addLiteralCharAndAdvance(); // '_' + scanDecimalDigits(); + } + if (m_source.isPastEndOfInput() || !isDecimalDigit(m_source.get(1))) + { + // A '.' has to be followed by a number. + literal.complete(); + return Token::Number; + } + addLiteralCharAndAdvance(); + scanDecimalDigits(); + } + } + } + // scan exponent, if any + if (m_char == 'e' || m_char == 'E') + { + solAssert(kind != HEX, "'e'/'E' must be scanned as part of the hex number"); + if (kind != DECIMAL) + return Token::Illegal; + else if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_') + { + // Recover from wrongly placed underscore as delimiter in literal with scientific + // notation by consuming until the end. + addLiteralCharAndAdvance(); // 'e' + addLiteralCharAndAdvance(); // '_' + scanDecimalDigits(); + literal.complete(); + return Token::Number; + } + // scan exponent + addLiteralCharAndAdvance(); // 'e' | 'E' + if (m_char == '+' || m_char == '-') + addLiteralCharAndAdvance(); + if (!isDecimalDigit(m_char)) + return Token::Illegal; // we must have at least one decimal digit after 'e'/'E' + scanDecimalDigits(); + } + // The source character immediately following a numeric literal must + // not be an identifier start or a decimal digit; see ECMA-262 + // section 7.8.3, page 17 (note that we read only one decimal digit + // if the value is 0). + if (isDecimalDigit(m_char) || isIdentifierStart(m_char)) + return Token::Illegal; + literal.complete(); + return Token::Number; +} + +tuple Scanner::scanIdentifierOrKeyword() +{ + solAssert(isIdentifierStart(m_char), ""); + LiteralScope literal(this, LITERAL_TYPE_STRING); + addLiteralCharAndAdvance(); + // Scan the rest of the identifier characters. + while (isIdentifierPart(m_char)) //get full literal + addLiteralCharAndAdvance(); + literal.complete(); + return TokenTraits::fromIdentifierOrKeyword(m_nextToken.literal); +} + +char CharStream::advanceAndGet(size_t _chars) +{ + if (isPastEndOfInput()) + return 0; + m_position += _chars; + if (isPastEndOfInput()) + return 0; + return m_source[m_position]; +} + +char CharStream::rollback(size_t _amount) +{ + solAssert(m_position >= _amount, ""); + m_position -= _amount; + return get(); +} + +string CharStream::lineAtPosition(int _position) const +{ + // if _position points to \n, it returns the line before the \n + using size_type = string::size_type; + size_type searchStart = min(m_source.size(), _position); + if (searchStart > 0) + searchStart--; + size_type lineStart = m_source.rfind('\n', searchStart); + if (lineStart == string::npos) + lineStart = 0; + else + lineStart++; + return m_source.substr(lineStart, min(m_source.find('\n', lineStart), + m_source.size()) - lineStart); +} + +tuple CharStream::translatePositionToLineColumn(int _position) const +{ + using size_type = string::size_type; + size_type searchPosition = min(m_source.size(), _position); + int lineNumber = count(m_source.begin(), m_source.begin() + searchPosition, '\n'); + size_type lineStart; + if (searchPosition == 0) + lineStart = 0; + else + { + lineStart = m_source.rfind('\n', searchPosition - 1); + lineStart = lineStart == string::npos ? 0 : lineStart + 1; + } + return tuple(lineNumber, searchPosition - lineStart); +} + + +} +} diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h new file mode 100644 index 00000000..d89f0c84 --- /dev/null +++ b/liblangutil/Scanner.h @@ -0,0 +1,249 @@ +/* + 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 . + + This file is derived from the file "scanner.h", which was part of the + V8 project. The original copyright header follows: + + Copyright 2006-2012, the V8 project authors. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/** + * @author Christian + * @date 2014 + * Solidity scanner. + */ + +#pragma once + +#include +#include +#include +#include + +namespace dev +{ +namespace solidity +{ + + +class AstRawString; +class AstValueFactory; +class ParserRecorder; + +class CharStream +{ +public: + CharStream(): m_position(0) {} + explicit CharStream(std::string const& _source): m_source(_source), m_position(0) {} + int position() const { return m_position; } + bool isPastEndOfInput(size_t _charsForward = 0) const { return (m_position + _charsForward) >= m_source.size(); } + char get(size_t _charsForward = 0) const { return m_source[m_position + _charsForward]; } + char advanceAndGet(size_t _chars = 1); + char rollback(size_t _amount); + + void reset() { m_position = 0; } + + std::string const& source() const { return m_source; } + + ///@{ + ///@name Error printing helper functions + /// Functions that help pretty-printing parse errors + /// Do only use in error cases, they are quite expensive. + std::string lineAtPosition(int _position) const; + std::tuple translatePositionToLineColumn(int _position) const; + ///@} + +private: + std::string m_source; + size_t m_position; +}; + + + +class Scanner +{ + friend class LiteralScope; +public: + + explicit Scanner(CharStream const& _source = CharStream(), std::string const& _sourceName = "") { reset(_source, _sourceName); } + + std::string source() const { return m_source.source(); } + + /// Resets the scanner as if newly constructed with _source and _sourceName as input. + void reset(CharStream const& _source, std::string const& _sourceName); + /// Resets scanner to the start of input. + void reset(); + + /// @returns the next token and advances input + Token next(); + + ///@{ + ///@name Information about the current token + + /// @returns the current token + Token currentToken() const + { + return m_currentToken.token; + } + ElementaryTypeNameToken currentElementaryTypeNameToken() const + { + unsigned firstSize; + unsigned secondSize; + std::tie(firstSize, secondSize) = m_currentToken.extendedTokenInfo; + return ElementaryTypeNameToken(m_currentToken.token, firstSize, secondSize); + } + + SourceLocation currentLocation() const { return m_currentToken.location; } + std::string const& currentLiteral() const { return m_currentToken.literal; } + std::tuple const& currentTokenInfo() const { return m_currentToken.extendedTokenInfo; } + ///@} + + ///@{ + ///@name Information about the current comment token + + SourceLocation currentCommentLocation() const { return m_skippedComment.location; } + std::string const& currentCommentLiteral() const { return m_skippedComment.literal; } + /// Called by the parser during FunctionDefinition parsing to clear the current comment + void clearCurrentCommentLiteral() { m_skippedComment.literal.clear(); } + + ///@} + + ///@{ + ///@name Information about the next token + + /// @returns the next token without advancing input. + Token peekNextToken() const { return m_nextToken.token; } + SourceLocation peekLocation() const { return m_nextToken.location; } + std::string const& peekLiteral() const { return m_nextToken.literal; } + ///@} + + std::shared_ptr const& sourceName() const { return m_sourceName; } + + ///@{ + ///@name Error printing helper functions + /// Functions that help pretty-printing parse errors + /// Do only use in error cases, they are quite expensive. + std::string lineAtPosition(int _position) const { return m_source.lineAtPosition(_position); } + std::tuple translatePositionToLineColumn(int _position) const { return m_source.translatePositionToLineColumn(_position); } + std::string sourceAt(SourceLocation const& _location) const + { + solAssert(!_location.isEmpty(), ""); + solAssert(m_sourceName && _location.sourceName, ""); + solAssert(*m_sourceName == *_location.sourceName, ""); + return m_source.source().substr(_location.start, _location.end - _location.start); + } + ///@} + +private: + /// Used for the current and look-ahead token and comments + struct TokenDesc + { + Token token; + SourceLocation location; + std::string literal; + std::tuple extendedTokenInfo; + }; + + ///@{ + ///@name Literal buffer support + inline void addLiteralChar(char c) { m_nextToken.literal.push_back(c); } + inline void addCommentLiteralChar(char c) { m_nextSkippedComment.literal.push_back(c); } + inline void addLiteralCharAndAdvance() { addLiteralChar(m_char); advance(); } + void addUnicodeAsUTF8(unsigned codepoint); + ///@} + + bool advance() { m_char = m_source.advanceAndGet(); return !m_source.isPastEndOfInput(); } + void rollback(int _amount) { m_char = m_source.rollback(_amount); } + + inline Token selectToken(Token _tok) { advance(); return _tok; } + /// If the next character is _next, advance and return _then, otherwise return _else. + inline Token selectToken(char _next, Token _then, Token _else); + + bool scanHexByte(char& o_scannedByte); + bool scanUnicode(unsigned& o_codepoint); + + /// Scans a single Solidity token. + void scanToken(); + + /// Skips all whitespace and @returns true if something was skipped. + bool skipWhitespace(); + /// Skips all whitespace that are neither '\r' nor '\n'. + void skipWhitespaceExceptUnicodeLinebreak(); + Token skipSingleLineComment(); + Token skipMultiLineComment(); + + void scanDecimalDigits(); + Token scanNumber(char _charSeen = 0); + std::tuple scanIdentifierOrKeyword(); + + Token scanString(); + Token scanHexString(); + Token scanSingleLineDocComment(); + Token scanMultiLineDocComment(); + /// Scans a slash '/' and depending on the characters returns the appropriate token + Token scanSlash(); + + /// Scans an escape-sequence which is part of a string and adds the + /// decoded character to the current literal. Returns true if a pattern + /// is scanned. + bool scanEscape(); + + /// @returns true iff we are currently positioned at a unicode line break. + bool isUnicodeLinebreak(); + + /// Return the current source position. + int sourcePos() const { return m_source.position(); } + bool isSourcePastEndOfInput() const { return m_source.isPastEndOfInput(); } + + TokenDesc m_skippedComment; // desc for current skipped comment + TokenDesc m_nextSkippedComment; // desc for next skipped comment + + TokenDesc m_currentToken; // desc for current token (as returned by Next()) + TokenDesc m_nextToken; // desc for next token (one token look-ahead) + + CharStream m_source; + std::shared_ptr m_sourceName; + + /// one character look-ahead, equals 0 at end of input + char m_char; +}; + +} +} diff --git a/liblangutil/SourceLocation.h b/liblangutil/SourceLocation.h new file mode 100644 index 00000000..b42c3aa9 --- /dev/null +++ b/liblangutil/SourceLocation.h @@ -0,0 +1,105 @@ +/* + 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 . +*/ +/** + * @author Lefteris Karapetsas + * @date 2015 + * Represents a location in a source file + */ + +#pragma once + +#include +#include +#include +#include +#include // defines noexcept macro for MSVC + +namespace dev +{ + +/** + * Representation of an interval of source positions. + * The interval includes start and excludes end. + */ +struct SourceLocation +{ + SourceLocation(): start(-1), end(-1) { } + SourceLocation(int _start, int _end, std::shared_ptr _sourceName): + start(_start), end(_end), sourceName(_sourceName) { } + SourceLocation(SourceLocation&& _other) noexcept: + start(_other.start), + end(_other.end), + sourceName(std::move(_other.sourceName)) + {} + SourceLocation(SourceLocation const&) = default; + SourceLocation& operator=(SourceLocation const&) = default; + SourceLocation& operator=(SourceLocation&& _other) noexcept + { + start = _other.start; + end = _other.end; + sourceName = std::move(_other.sourceName); + return *this; + } + + bool operator==(SourceLocation const& _other) const + { + return start == _other.start && end == _other.end && + ((!sourceName && !_other.sourceName) || (sourceName && _other.sourceName && *sourceName == *_other.sourceName)); + } + bool operator!=(SourceLocation const& _other) const { return !operator==(_other); } + inline bool operator<(SourceLocation const& _other) const; + inline bool contains(SourceLocation const& _other) const; + inline bool intersects(SourceLocation const& _other) const; + + bool isEmpty() const { return start == -1 && end == -1; } + + int start; + int end; + std::shared_ptr sourceName; +}; + +/// Stream output for Location (used e.g. in boost exceptions). +inline std::ostream& operator<<(std::ostream& _out, SourceLocation const& _location) +{ + if (_location.isEmpty()) + return _out << "NO_LOCATION_SPECIFIED"; + return _out << *_location.sourceName << "[" << _location.start << "," << _location.end << ")"; +} + +bool SourceLocation::operator<(SourceLocation const& _other) const +{ + if (!sourceName || !_other.sourceName) + return std::make_tuple(int(!!sourceName), start, end) < std::make_tuple(int(!!_other.sourceName), _other.start, _other.end); + else + return std::make_tuple(*sourceName, start, end) < std::make_tuple(*_other.sourceName, _other.start, _other.end); +} + +bool SourceLocation::contains(SourceLocation const& _other) const +{ + if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName))) + return false; + return start <= _other.start && _other.end <= end; +} + +bool SourceLocation::intersects(SourceLocation const& _other) const +{ + if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName))) + return false; + return _other.start < end && start < _other.end; +} + +} diff --git a/liblangutil/Token.cpp b/liblangutil/Token.cpp new file mode 100644 index 00000000..2e754733 --- /dev/null +++ b/liblangutil/Token.cpp @@ -0,0 +1,207 @@ +// Copyright 2006-2012, the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Modifications as part of solidity under the following license: +// +// 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 . + +#include +#include +#include + +using namespace std; + +namespace dev +{ +namespace solidity +{ + +void ElementaryTypeNameToken::assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second) +{ + solAssert(TokenTraits::isElementaryTypeName(_baseType), "Expected elementary type name: " + string(TokenTraits::toString(_baseType))); + if (_baseType == Token::BytesM) + { + solAssert(_second == 0, "There should not be a second size argument to type bytesM."); + solAssert(_first <= 32, "No elementary type bytes" + to_string(_first) + "."); + } + else if (_baseType == Token::UIntM || _baseType == Token::IntM) + { + solAssert(_second == 0, "There should not be a second size argument to type " + string(TokenTraits::toString(_baseType)) + "."); + solAssert( + _first <= 256 && _first % 8 == 0, + "No elementary type " + string(TokenTraits::toString(_baseType)) + to_string(_first) + "." + ); + } + else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN) + { + solAssert( + _first >= 8 && _first <= 256 && _first % 8 == 0 && _second <= 80, + "No elementary type " + string(TokenTraits::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "." + ); + } + m_token = _baseType; + m_firstNumber = _first; + m_secondNumber = _second; +} + +namespace TokenTraits +{ + +char const* toString(Token tok) +{ + switch (tok) + { +#define T(name, string, precedence) case Token::name: return string; + TOKEN_LIST(T, T) +#undef T + default: // Token::NUM_TOKENS: + return ""; + } +} + +char const* name(Token tok) +{ +#define T(name, string, precedence) #name, + static char const* const names[TokenTraits::count()] = { TOKEN_LIST(T, T) }; +#undef T + + solAssert(static_cast(tok) < TokenTraits::count(), ""); + return names[static_cast(tok)]; +} + +std::string friendlyName(Token tok) +{ + char const* ret = toString(tok); + if (ret) + return std::string(ret); + + ret = name(tok); + solAssert(ret != nullptr, ""); + return std::string(ret); +} + +#define T(name, string, precedence) precedence, +int precedence(Token tok) +{ + int8_t const static precs[TokenTraits::count()] = + { + TOKEN_LIST(T, T) + }; + return precs[static_cast(tok)]; +} +#undef T + +int parseSize(string::const_iterator _begin, string::const_iterator _end) +{ + try + { + unsigned int m = boost::lexical_cast(boost::make_iterator_range(_begin, _end)); + return m; + } + catch(boost::bad_lexical_cast const&) + { + return -1; + } +} + +static Token keywordByName(string const& _name) +{ + // The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored + // and keywords to be put inside the keywords variable. +#define KEYWORD(name, string, precedence) {string, Token::name}, +#define TOKEN(name, string, precedence) + static const map keywords({TOKEN_LIST(TOKEN, KEYWORD)}); +#undef KEYWORD +#undef TOKEN + auto it = keywords.find(_name); + return it == keywords.end() ? Token::Identifier : it->second; +} + +tuple fromIdentifierOrKeyword(string const& _literal) +{ + auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit); + if (positionM != _literal.end()) + { + string baseType(_literal.begin(), positionM); + auto positionX = find_if_not(positionM, _literal.end(), ::isdigit); + int m = parseSize(positionM, positionX); + Token keyword = keywordByName(baseType); + if (keyword == Token::Bytes) + { + if (0 < m && m <= 32 && positionX == _literal.end()) + return make_tuple(Token::BytesM, m, 0); + } + else if (keyword == Token::UInt || keyword == Token::Int) + { + if (0 < m && m <= 256 && m % 8 == 0 && positionX == _literal.end()) + { + if (keyword == Token::UInt) + return make_tuple(Token::UIntM, m, 0); + else + return make_tuple(Token::IntM, m, 0); + } + } + else if (keyword == Token::UFixed || keyword == Token::Fixed) + { + if ( + positionM < positionX && + positionX < _literal.end() && + *positionX == 'x' && + all_of(positionX + 1, _literal.end(), ::isdigit) + ) { + int n = parseSize(positionX + 1, _literal.end()); + if ( + 8 <= m && m <= 256 && m % 8 == 0 && + 0 <= n && n <= 80 + ) { + if (keyword == Token::UFixed) + return make_tuple(Token::UFixedMxN, m, n); + else + return make_tuple(Token::FixedMxN, m, n); + } + } + } + return make_tuple(Token::Identifier, 0, 0); + } + + return make_tuple(keywordByName(_literal), 0, 0); +} + +} +} +} diff --git a/liblangutil/Token.h b/liblangutil/Token.h new file mode 100644 index 00000000..89dd4c01 --- /dev/null +++ b/liblangutil/Token.h @@ -0,0 +1,378 @@ +// Copyright 2006-2012, the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Modifications as part of solidity under the following license: +// +// 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 . + +#pragma once + +#include +#include +#include +#include + +namespace dev +{ +namespace solidity +{ + +// TOKEN_LIST takes a list of 3 macros M, all of which satisfy the +// same signature M(name, string, precedence), where name is the +// symbolic token name, string is the corresponding syntactic symbol +// (or NULL, for literals), and precedence is the precedence (or 0). +// The parameters are invoked for token categories as follows: +// +// T: Non-keyword tokens +// K: Keyword tokens + +// IGNORE_TOKEN is a convenience macro that can be supplied as +// an argument (at any position) for a TOKEN_LIST call. It does +// nothing with tokens belonging to the respective category. + +#define IGNORE_TOKEN(name, string, precedence) + +#define TOKEN_LIST(T, K) \ + /* End of source indicator. */ \ + T(EOS, "EOS", 0) \ + \ + /* Punctuators (ECMA-262, section 7.7, page 15). */ \ + T(LParen, "(", 0) \ + T(RParen, ")", 0) \ + T(LBrack, "[", 0) \ + T(RBrack, "]", 0) \ + T(LBrace, "{", 0) \ + T(RBrace, "}", 0) \ + T(Colon, ":", 0) \ + T(Semicolon, ";", 0) \ + T(Period, ".", 0) \ + T(Conditional, "?", 3) \ + T(Arrow, "=>", 0) \ + \ + /* Assignment operators. */ \ + /* IsAssignmentOp() relies on this block of enum values being */ \ + /* contiguous and sorted in the same order!*/ \ + T(Assign, "=", 2) \ + /* The following have to be in exactly the same order as the simple binary operators*/ \ + T(AssignBitOr, "|=", 2) \ + T(AssignBitXor, "^=", 2) \ + T(AssignBitAnd, "&=", 2) \ + T(AssignShl, "<<=", 2) \ + T(AssignSar, ">>=", 2) \ + T(AssignShr, ">>>=", 2) \ + T(AssignAdd, "+=", 2) \ + T(AssignSub, "-=", 2) \ + T(AssignMul, "*=", 2) \ + T(AssignDiv, "/=", 2) \ + T(AssignMod, "%=", 2) \ + \ + /* Binary operators sorted by precedence. */ \ + /* IsBinaryOp() relies on this block of enum values */ \ + /* being contiguous and sorted in the same order! */ \ + T(Comma, ",", 1) \ + T(Or, "||", 4) \ + T(And, "&&", 5) \ + T(BitOr, "|", 8) \ + T(BitXor, "^", 9) \ + T(BitAnd, "&", 10) \ + T(SHL, "<<", 11) \ + T(SAR, ">>", 11) \ + T(SHR, ">>>", 11) \ + T(Add, "+", 12) \ + T(Sub, "-", 12) \ + T(Mul, "*", 13) \ + T(Div, "/", 13) \ + T(Mod, "%", 13) \ + T(Exp, "**", 14) \ + \ + /* Compare operators sorted by precedence. */ \ + /* IsCompareOp() relies on this block of enum values */ \ + /* being contiguous and sorted in the same order! */ \ + T(Equal, "==", 6) \ + T(NotEqual, "!=", 6) \ + T(LessThan, "<", 7) \ + T(GreaterThan, ">", 7) \ + T(LessThanOrEqual, "<=", 7) \ + T(GreaterThanOrEqual, ">=", 7) \ + \ + /* Unary operators. */ \ + /* IsUnaryOp() relies on this block of enum values */ \ + /* being contiguous and sorted in the same order! */ \ + T(Not, "!", 0) \ + T(BitNot, "~", 0) \ + T(Inc, "++", 0) \ + T(Dec, "--", 0) \ + K(Delete, "delete", 0) \ + \ + /* Keywords */ \ + K(Anonymous, "anonymous", 0) \ + K(As, "as", 0) \ + K(Assembly, "assembly", 0) \ + K(Break, "break", 0) \ + K(Constant, "constant", 0) \ + K(Constructor, "constructor", 0) \ + K(Continue, "continue", 0) \ + K(Contract, "contract", 0) \ + K(Do, "do", 0) \ + K(Else, "else", 0) \ + K(Enum, "enum", 0) \ + K(Emit, "emit", 0) \ + K(Event, "event", 0) \ + K(External, "external", 0) \ + K(For, "for", 0) \ + K(Function, "function", 0) \ + K(Hex, "hex", 0) \ + K(If, "if", 0) \ + K(Indexed, "indexed", 0) \ + K(Interface, "interface", 0) \ + K(Internal, "internal", 0) \ + K(Import, "import", 0) \ + K(Is, "is", 0) \ + K(Library, "library", 0) \ + K(Mapping, "mapping", 0) \ + K(Memory, "memory", 0) \ + K(Modifier, "modifier", 0) \ + K(New, "new", 0) \ + K(Payable, "payable", 0) \ + K(Public, "public", 0) \ + K(Pragma, "pragma", 0) \ + K(Private, "private", 0) \ + K(Pure, "pure", 0) \ + K(Return, "return", 0) \ + K(Returns, "returns", 0) \ + K(Storage, "storage", 0) \ + K(CallData, "calldata", 0) \ + K(Struct, "struct", 0) \ + K(Throw, "throw", 0) \ + K(Using, "using", 0) \ + K(Var, "var", 0) \ + K(View, "view", 0) \ + K(While, "while", 0) \ + \ + /* Ether subdenominations */ \ + K(SubWei, "wei", 0) \ + K(SubSzabo, "szabo", 0) \ + K(SubFinney, "finney", 0) \ + K(SubEther, "ether", 0) \ + K(SubSecond, "seconds", 0) \ + K(SubMinute, "minutes", 0) \ + K(SubHour, "hours", 0) \ + K(SubDay, "days", 0) \ + K(SubWeek, "weeks", 0) \ + K(SubYear, "years", 0) \ + /* type keywords*/ \ + K(Int, "int", 0) \ + K(UInt, "uint", 0) \ + K(Bytes, "bytes", 0) \ + K(Byte, "byte", 0) \ + K(String, "string", 0) \ + K(Address, "address", 0) \ + K(Bool, "bool", 0) \ + K(Fixed, "fixed", 0) \ + K(UFixed, "ufixed", 0) \ + T(IntM, "intM", 0) \ + T(UIntM, "uintM", 0) \ + T(BytesM, "bytesM", 0) \ + T(FixedMxN, "fixedMxN", 0) \ + T(UFixedMxN, "ufixedMxN", 0) \ + T(TypesEnd, NULL, 0) /* used as type enum end marker */ \ + \ + /* Literals */ \ + K(TrueLiteral, "true", 0) \ + K(FalseLiteral, "false", 0) \ + T(Number, NULL, 0) \ + T(StringLiteral, NULL, 0) \ + T(CommentLiteral, NULL, 0) \ + \ + /* Identifiers (not keywords or future reserved words). */ \ + T(Identifier, NULL, 0) \ + \ + /* Keywords reserved for future use. */ \ + K(Abstract, "abstract", 0) \ + K(After, "after", 0) \ + K(Alias, "alias", 0) \ + K(Apply, "apply", 0) \ + K(Auto, "auto", 0) \ + K(Case, "case", 0) \ + K(Catch, "catch", 0) \ + K(CopyOf, "copyof", 0) \ + K(Default, "default", 0) \ + K(Define, "define", 0) \ + K(Final, "final", 0) \ + K(Immutable, "immutable", 0) \ + K(Implements, "implements", 0) \ + K(In, "in", 0) \ + K(Inline, "inline", 0) \ + K(Let, "let", 0) \ + K(Macro, "macro", 0) \ + K(Match, "match", 0) \ + K(Mutable, "mutable", 0) \ + K(NullLiteral, "null", 0) \ + K(Of, "of", 0) \ + K(Override, "override", 0) \ + K(Partial, "partial", 0) \ + K(Promise, "promise", 0) \ + K(Reference, "reference", 0) \ + K(Relocatable, "relocatable", 0) \ + K(Sealed, "sealed", 0) \ + K(Sizeof, "sizeof", 0) \ + K(Static, "static", 0) \ + K(Supports, "supports", 0) \ + K(Switch, "switch", 0) \ + K(Try, "try", 0) \ + K(Type, "type", 0) \ + K(Typedef, "typedef", 0) \ + K(TypeOf, "typeof", 0) \ + K(Unchecked, "unchecked", 0) \ + \ + /* Illegal token - not able to scan. */ \ + T(Illegal, "ILLEGAL", 0) \ + /* Illegal hex token */ \ + T(IllegalHex, "ILLEGAL_HEX", 0) \ + \ + /* Scanner-internal use only. */ \ + T(Whitespace, NULL, 0) + +// All token values. +// attention! msvc issue: +// http://stackoverflow.com/questions/9567868/compile-errors-after-adding-v8-to-my-project-c2143-c2059 +// @todo: avoid TOKEN_LIST macro +enum class Token : unsigned int { +#define T(name, string, precedence) name, + TOKEN_LIST(T, T) + NUM_TOKENS +#undef T +}; + +namespace TokenTraits +{ + constexpr size_t count() { return static_cast(Token::NUM_TOKENS); } + + // Predicates + constexpr bool isElementaryTypeName(Token tok) { return Token::Int <= tok && tok < Token::TypesEnd; } + constexpr bool isAssignmentOp(Token tok) { return Token::Assign <= tok && tok <= Token::AssignMod; } + constexpr bool isBinaryOp(Token op) { return Token::Comma <= op && op <= Token::Exp; } + constexpr bool isCommutativeOp(Token op) { return op == Token::BitOr || op == Token::BitXor || op == Token::BitAnd || + op == Token::Add || op == Token::Mul || op == Token::Equal || op == Token::NotEqual; } + constexpr bool isArithmeticOp(Token op) { return Token::Add <= op && op <= Token::Exp; } + constexpr bool isCompareOp(Token op) { return Token::Equal <= op && op <= Token::GreaterThanOrEqual; } + + constexpr bool isBitOp(Token op) { return (Token::BitOr <= op && op <= Token::BitAnd) || op == Token::BitNot; } + constexpr bool isBooleanOp(Token op) { return (Token::Or <= op && op <= Token::And) || op == Token::Not; } + constexpr bool isUnaryOp(Token op) { return (Token::Not <= op && op <= Token::Delete) || op == Token::Add || op == Token::Sub; } + constexpr bool isCountOp(Token op) { return op == Token::Inc || op == Token::Dec; } + constexpr bool isShiftOp(Token op) { return (Token::SHL <= op) && (op <= Token::SHR); } + constexpr bool isVariableVisibilitySpecifier(Token op) { return op == Token::Public || op == Token::Private || op == Token::Internal; } + constexpr bool isVisibilitySpecifier(Token op) { return isVariableVisibilitySpecifier(op) || op == Token::External; } + constexpr bool isLocationSpecifier(Token op) { return op == Token::Memory || op == Token::Storage || op == Token::CallData; } + + constexpr bool isStateMutabilitySpecifier(Token op, bool _allowConstant = true) + { + return (op == Token::Constant && _allowConstant) + || op == Token::Pure || op == Token::View || op == Token::Payable; + } + + constexpr bool isEtherSubdenomination(Token op) { return op == Token::SubWei || op == Token::SubSzabo || op == Token::SubFinney || op == Token::SubEther; } + constexpr bool isTimeSubdenomination(Token op) { return op == Token::SubSecond || op == Token::SubMinute || op == Token::SubHour || op == Token::SubDay || op == Token::SubWeek || op == Token::SubYear; } + constexpr bool isReservedKeyword(Token op) { return (Token::Abstract <= op && op <= Token::Unchecked); } + + inline Token AssignmentToBinaryOp(Token op) + { + solAssert(isAssignmentOp(op) && op != Token::Assign, ""); + return static_cast(static_cast(op) + (static_cast(Token::BitOr) - static_cast(Token::AssignBitOr))); + } + + // @returns the precedence > 0 for binary and compare + // operators; returns 0 otherwise. + int precedence(Token tok); + + std::tuple fromIdentifierOrKeyword(std::string const& _literal); + + // @returns a string corresponding to the C++ token name + // (e.g. "LT" for the token LT). + char const* name(Token tok); + + // @returns a string corresponding to the JS token string + // (.e., "<" for the token LT) or NULL if the token doesn't + // have a (unique) string (e.g. an IDENTIFIER). + char const* toString(Token tok); + + std::string friendlyName(Token tok); +} + +inline std::ostream& operator<<(std::ostream& os, Token token) +{ + os << TokenTraits::friendlyName(token); + return os; +} + +class ElementaryTypeNameToken +{ +public: + ElementaryTypeNameToken(Token _token, unsigned const& _firstNumber, unsigned const& _secondNumber) + { + assertDetails(_token, _firstNumber, _secondNumber); + } + + unsigned int firstNumber() const { return m_firstNumber; } + unsigned int secondNumber() const { return m_secondNumber; } + Token token() const { return m_token; } + + ///if tokValue is set to true, then returns the actual token type name, otherwise, returns full type + std::string toString(bool const& tokenValue = false) const + { + std::string name = TokenTraits::toString(m_token); + if (tokenValue || (firstNumber() == 0 && secondNumber() == 0)) + return name; + solAssert(name.size() >= 3, "Token name size should be greater than 3. Should not reach here."); + if (m_token == Token::FixedMxN || m_token == Token::UFixedMxN) + return name.substr(0, name.size() - 3) + std::to_string(m_firstNumber) + "x" + std::to_string(m_secondNumber); + else + return name.substr(0, name.size() - 1) + std::to_string(m_firstNumber); + } + +private: + Token m_token; + unsigned int m_firstNumber; + unsigned int m_secondNumber; + /// throws if type is not properly sized + void assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second); +}; + +} +} diff --git a/liblangutil/UndefMacros.h b/liblangutil/UndefMacros.h new file mode 100644 index 00000000..d96e242e --- /dev/null +++ b/liblangutil/UndefMacros.h @@ -0,0 +1,46 @@ +/* + 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 . +*/ +/** @file UndefMacros.h + * @author Lefteris + * @date 2015 + * + * This header should be used to #undef some really evil macros defined by + * windows.h which result in conflict with our Token.h + */ +#pragma once + +#if defined(_MSC_VER) || defined(__MINGW32__) + +#undef DELETE +#undef IN +#undef VOID +#undef THIS +#undef CONST + +// Conflicting define on MinGW in windows.h +// windows.h(19): #define interface struct +#ifdef interface +#undef interface +#endif + +#elif defined(DELETE) || defined(IN) || defined(VOID) || defined(THIS) || defined(CONST) || defined(interface) + +#error "The preceding macros in this header file are reserved for V8's "\ +"TOKEN_LIST. Please add a platform specific define above to undefine "\ +"overlapping macros." + +#endif diff --git a/liblll/Compiler.h b/liblll/Compiler.h index 1ff7d5f8..93235cdd 100644 --- a/liblll/Compiler.h +++ b/liblll/Compiler.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 136d39b1..5f261f64 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,6 +1,6 @@ # Until we have a clear separation, libyul has to be included here -file(GLOB_RECURSE sources "*.cpp" "../libyul/*.cpp") -file(GLOB_RECURSE headers "*.h" "../libyul/*.h") +file(GLOB_RECURSE sources "*.cpp" "../libyul/*.cpp" "../liblangutil/*.cpp") +file(GLOB_RECURSE headers "*.h" "../libyul/*.h" "../liblangutil/*.h") find_package(Z3 QUIET) if (${Z3_FOUND}) diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index f9b00927..9d041ce5 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include using namespace std; using namespace dev; diff --git a/libsolidity/analysis/ControlFlowGraph.h b/libsolidity/analysis/ControlFlowGraph.h index 3f4820b8..257ce07f 100644 --- a/libsolidity/analysis/ControlFlowGraph.h +++ b/libsolidity/analysis/ControlFlowGraph.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/analysis/DocStringAnalyser.cpp b/libsolidity/analysis/DocStringAnalyser.cpp index c1b97def..f91d72f0 100644 --- a/libsolidity/analysis/DocStringAnalyser.cpp +++ b/libsolidity/analysis/DocStringAnalyser.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include using namespace std; diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index b452a49a..a6c746ed 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index 240d7973..3f45df42 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 2adc8e77..cae92203 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -23,12 +23,12 @@ #include #include #include -#include +#include #include #include #include #include -#include +#include #include diff --git a/libsolidity/analysis/SemVerHandler.h b/libsolidity/analysis/SemVerHandler.h index 03a557c5..edf4fbd8 100644 --- a/libsolidity/analysis/SemVerHandler.h +++ b/libsolidity/analysis/SemVerHandler.h @@ -23,7 +23,7 @@ #pragma once #include -#include +#include namespace dev { diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index 487a5cca..353c1755 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 3f9f8373..9ac0478e 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index c5e6488b..7531da65 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index ae3ebc52..392a923c 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include #include diff --git a/libsolidity/analysis/ViewPureChecker.h b/libsolidity/analysis/ViewPureChecker.h index 1109ad76..9615d04f 100644 --- a/libsolidity/analysis/ViewPureChecker.h +++ b/libsolidity/analysis/ViewPureChecker.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 23a6078b..2c44841e 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -24,12 +24,12 @@ #include -#include +#include #include #include #include -#include +#include #include #include diff --git a/libsolidity/ast/ASTEnums.h b/libsolidity/ast/ASTEnums.h index 5ba21907..d47a5f05 100644 --- a/libsolidity/ast/ASTEnums.h +++ b/libsolidity/ast/ASTEnums.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h index 8429708c..da0d840a 100644 --- a/libsolidity/ast/ASTJsonConverter.h +++ b/libsolidity/ast/ASTJsonConverter.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index fbf11f49..79a656e9 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -22,10 +22,10 @@ #pragma once -#include +#include #include #include -#include +#include #include #include diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index e9ffe4fb..d2132258 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index d33f749c..a4000d60 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 4028ae63..48d9e9d6 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -23,7 +23,7 @@ #pragma once #include -#include +#include #include diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 6e14d68a..fa6dfe60 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -25,9 +25,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include #include diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 5bdc1d19..63365175 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -24,7 +24,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 1fdf3483..c8d9d9d3 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h index 9a695b4c..2bfaab43 100644 --- a/libsolidity/codegen/ExpressionCompiler.h +++ b/libsolidity/codegen/ExpressionCompiler.h @@ -25,10 +25,10 @@ #include #include #include -#include +#include #include #include -#include +#include namespace dev { namespace eth diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h index 6054af28..f39eaee1 100644 --- a/libsolidity/codegen/LValue.h +++ b/libsolidity/codegen/LValue.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include namespace dev diff --git a/libsolidity/formal/CVC4Interface.cpp b/libsolidity/formal/CVC4Interface.cpp index 6e17eef1..8952665f 100644 --- a/libsolidity/formal/CVC4Interface.cpp +++ b/libsolidity/formal/CVC4Interface.cpp @@ -17,7 +17,7 @@ #include -#include +#include #include diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 0a581fc0..a8595190 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index 3bf84ac9..ae9f32e9 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -25,7 +25,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp index 01386dda..7a6b558b 100644 --- a/libsolidity/formal/SMTLib2Interface.cpp +++ b/libsolidity/formal/SMTLib2Interface.cpp @@ -17,7 +17,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/formal/SMTLib2Interface.h b/libsolidity/formal/SMTLib2Interface.h index b140f555..f3c58d6b 100644 --- a/libsolidity/formal/SMTLib2Interface.h +++ b/libsolidity/formal/SMTLib2Interface.h @@ -19,7 +19,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index 55c0a563..df036190 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -17,7 +17,7 @@ #pragma once -#include +#include #include #include diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 09696aeb..ac6fbd54 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -17,7 +17,7 @@ #include -#include +#include #include diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index ac019c06..95c8537d 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index a8673efa..7ae27ebd 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -20,8 +20,8 @@ #pragma once -#include -#include +#include +#include #include diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 3a62b232..ee69b44f 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index a8d5e327..e9bf4841 100644 --- a/libsolidity/inlineasm/AsmData.h +++ b/libsolidity/inlineasm/AsmData.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 1f399edc..3103e2b3 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -21,8 +21,8 @@ */ #include -#include -#include +#include +#include #include diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h index 41117228..b3d74df1 100644 --- a/libsolidity/inlineasm/AsmParser.h +++ b/libsolidity/inlineasm/AsmParser.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include namespace dev { diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp index ae0bd1eb..7151fcfa 100644 --- a/libsolidity/inlineasm/AsmPrinter.cpp +++ b/libsolidity/inlineasm/AsmPrinter.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h index 65848018..12c05716 100644 --- a/libsolidity/inlineasm/AsmScope.h +++ b/libsolidity/inlineasm/AsmScope.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp index d1f98083..c7625fe0 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.cpp +++ b/libsolidity/inlineasm/AsmScopeFiller.cpp @@ -24,8 +24,8 @@ #include #include -#include -#include +#include +#include #include diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 26496de7..26879e8b 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -22,7 +22,7 @@ #include -#include +#include #include #include #include diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index 8132ce63..aad65ffc 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -21,8 +21,8 @@ #pragma once -#include -#include +#include +#include #include diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index d6a63f1d..08a248dd 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 9a15fbf0..a7e312ad 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -23,11 +23,11 @@ #pragma once -#include +#include #include -#include +#include -#include +#include #include #include diff --git a/libsolidity/interface/EVMVersion.h b/libsolidity/interface/EVMVersion.h deleted file mode 100644 index 657727ac..00000000 --- a/libsolidity/interface/EVMVersion.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - 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 . -*/ -/** - * EVM versioning. - */ - -#pragma once - -#include - -#include -#include - -namespace dev -{ -namespace solidity -{ - -/** - * A version specifier of the EVM we want to compile to. - * Defaults to the latest version. - */ -class EVMVersion: - boost::less_than_comparable, - boost::equality_comparable -{ -public: - EVMVersion() {} - - static EVMVersion homestead() { return {Version::Homestead}; } - static EVMVersion tangerineWhistle() { return {Version::TangerineWhistle}; } - static EVMVersion spuriousDragon() { return {Version::SpuriousDragon}; } - static EVMVersion byzantium() { return {Version::Byzantium}; } - static EVMVersion constantinople() { return {Version::Constantinople}; } - - static boost::optional fromString(std::string const& _version) - { - for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople()}) - if (_version == v.name()) - return v; - return {}; - } - - bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; } - bool operator<(EVMVersion const& _other) const { return m_version < _other.m_version; } - - std::string name() const - { - switch (m_version) - { - case Version::Homestead: return "homestead"; - case Version::TangerineWhistle: return "tangerineWhistle"; - case Version::SpuriousDragon: return "spuriousDragon"; - case Version::Byzantium: return "byzantium"; - case Version::Constantinople: return "constantinople"; - } - return "INVALID"; - } - - /// Has the RETURNDATACOPY and RETURNDATASIZE opcodes. - bool supportsReturndata() const { return *this >= byzantium(); } - bool hasStaticCall() const { return *this >= byzantium(); } - bool hasBitwiseShifting() const { return *this >= constantinople(); } - bool hasCreate2() const { return *this >= constantinople(); } - - /// Whether we have to retain the costs for the call opcode itself (false), - /// or whether we can just forward easily all remaining gas (true). - bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); } - -private: - enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople }; - - EVMVersion(Version _version): m_version(_version) {} - - Version m_version = Version::Byzantium; -}; - - -} -} diff --git a/libsolidity/interface/ErrorReporter.cpp b/libsolidity/interface/ErrorReporter.cpp deleted file mode 100644 index 368e25e0..00000000 --- a/libsolidity/interface/ErrorReporter.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - 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 . -*/ -/** - * @author Rhett - * @date 2017 - * Error helper class. - */ - -#include -#include -#include - -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::warning( - SourceLocation const& _location, - string const& _description, - SecondarySourceLocation const& _secondaryLocation -) -{ - error(Error::Type::Warning, _location, _secondaryLocation, _description); -} - -void ErrorReporter::error(Error::Type _type, SourceLocation const& _location, string const& _description) -{ - if (checkForExcessiveErrors(_type)) - return; - - auto err = make_shared(_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) -{ - if (checkForExcessiveErrors(_type)) - return; - - auto err = make_shared(_type); - *err << - errinfo_sourceLocation(_location) << - errinfo_secondarySourceLocation(_secondaryLocation) << - errinfo_comment(_description); - - m_errorList.push_back(err); -} - -bool ErrorReporter::checkForExcessiveErrors(Error::Type _type) -{ - if (_type == Error::Type::Warning) - { - m_warningCount++; - - if (m_warningCount == c_maxWarningsAllowed) - { - auto err = make_shared(Error::Type::Warning); - *err << errinfo_comment("There are more than 256 warnings. Ignoring the rest."); - m_errorList.push_back(err); - } - - if (m_warningCount >= c_maxWarningsAllowed) - return true; - } - else - { - m_errorCount++; - - if (m_errorCount > c_maxErrorsAllowed) - { - auto err = make_shared(Error::Type::Warning); - *err << errinfo_comment("There are more than 256 errors. Aborting."); - m_errorList.push_back(err); - BOOST_THROW_EXCEPTION(FatalError()); - } - } - - return false; -} - -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, SecondarySourceLocation const& _secondaryLocation, string const& _description) -{ - error( - Error::Type::TypeError, - _location, - _secondaryLocation, - _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 - ); -} diff --git a/libsolidity/interface/ErrorReporter.h b/libsolidity/interface/ErrorReporter.h deleted file mode 100644 index fd53587a..00000000 --- a/libsolidity/interface/ErrorReporter.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - 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 . -*/ -/** - * @author Rhett - * @date 2017 - * Error reporting helper class. - */ - -#pragma once - -#include -#include - -namespace dev -{ -namespace solidity -{ - -class ASTNode; - -class ErrorReporter -{ -public: - - explicit ErrorReporter(ErrorList& _errors): - m_errorList(_errors) { } - - ErrorReporter(ErrorReporter const& _errorReporter) noexcept: - m_errorList(_errorReporter.m_errorList) { } - - ErrorReporter& operator=(ErrorReporter const& _errorReporter); - - void warning(std::string const& _description); - - void warning(SourceLocation const& _location, std::string const& _description); - - void warning( - SourceLocation const& _location, - std::string const& _description, - SecondarySourceLocation const& _secondaryLocation - ); - - void error( - Error::Type _type, - SourceLocation const& _location, - std::string const& _description - ); - - void declarationError( - SourceLocation const& _location, - SecondarySourceLocation const& _secondaryLocation, - std::string const& _description - ); - - void declarationError(SourceLocation const& _location, std::string const& _description); - - 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, - SecondarySourceLocation const& _secondaryLocation = SecondarySourceLocation(), - std::string const& _description = std::string() - ); - - void typeError(SourceLocation const& _location, std::string const& _description); - - void fatalTypeError(SourceLocation const& _location, std::string const& _description); - - void docstringParsingError(std::string const& _description); - - ErrorList const& errors() const; - - void clear(); - - /// @returns true iff there is any error (ignores warnings). - bool hasErrors() const - { - return m_errorCount > 0; - } - -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()); - - // @returns true if error shouldn't be stored - bool checkForExcessiveErrors(Error::Type _type); - - ErrorList& m_errorList; - - unsigned m_errorCount = 0; - unsigned m_warningCount = 0; - - const unsigned c_maxWarningsAllowed = 256; - const unsigned c_maxErrorsAllowed = 256; -}; - - -} -} - diff --git a/libsolidity/interface/Exceptions.cpp b/libsolidity/interface/Exceptions.cpp deleted file mode 100644 index ecadd0b7..00000000 --- a/libsolidity/interface/Exceptions.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - 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 . -*/ -/** - * @author Liana - * @date 2015 - * Solidity exception hierarchy. - */ - -#include - -using namespace std; -using namespace dev; -using namespace dev::solidity; - -Error::Error(Type _type, SourceLocation const& _location, string const& _description): - m_type(_type) -{ - switch(m_type) - { - case Type::DeclarationError: - m_typeName = "DeclarationError"; - break; - case Type::DocstringParsingError: - m_typeName = "DocstringParsingError"; - break; - case Type::ParserError: - m_typeName = "ParserError"; - break; - case Type::SyntaxError: - m_typeName = "SyntaxError"; - break; - case Type::TypeError: - m_typeName = "TypeError"; - break; - case Type::Warning: - m_typeName = "Warning"; - break; - } - - if (!_location.isEmpty()) - *this << errinfo_sourceLocation(_location); - if (!_description.empty()) - *this << errinfo_comment(_description); -} - -Error::Error(Error::Type _type, const std::string& _description, const SourceLocation& _location): - Error(_type) -{ - if (!_location.isEmpty()) - *this << errinfo_sourceLocation(_location); - *this << errinfo_comment(_description); -} diff --git a/libsolidity/interface/Exceptions.h b/libsolidity/interface/Exceptions.h deleted file mode 100644 index 629b8f3f..00000000 --- a/libsolidity/interface/Exceptions.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - 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 . -*/ -/** - * @author Christian - * @date 2014 - * Solidity exception hierarchy. - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace dev -{ -namespace solidity -{ -class Error; -using ErrorList = std::vector>; - -struct CompilerError: virtual Exception {}; -struct InternalCompilerError: virtual Exception {}; -struct FatalError: virtual Exception {}; -struct UnimplementedFeatureError: virtual Exception{}; - -/// Assertion that throws an InternalCompilerError containing the given description if it is not met. -#define solAssert(CONDITION, DESCRIPTION) \ - assertThrow(CONDITION, ::dev::solidity::InternalCompilerError, DESCRIPTION) - -#define solUnimplementedAssert(CONDITION, DESCRIPTION) \ - assertThrow(CONDITION, ::dev::solidity::UnimplementedFeatureError, DESCRIPTION) - -#define solUnimplemented(DESCRIPTION) \ - solUnimplementedAssert(false, DESCRIPTION) - -class Error: virtual public Exception -{ -public: - enum class Type - { - DeclarationError, - DocstringParsingError, - ParserError, - TypeError, - SyntaxError, - Warning - }; - - explicit Error( - Type _type, - SourceLocation const& _location = SourceLocation(), - std::string const& _description = std::string() - ); - - Error(Type _type, std::string const& _description, SourceLocation const& _location = SourceLocation()); - - Type type() const { return m_type; } - std::string const& typeName() const { return m_typeName; } - - /// helper functions - static Error const* containsErrorOfType(ErrorList const& _list, Error::Type _type) - { - for (auto e: _list) - { - if (e->type() == _type) - return e.get(); - } - return nullptr; - } - static bool containsOnlyWarnings(ErrorList const& _list) - { - for (auto e: _list) - { - if (e->type() != Type::Warning) - return false; - } - return true; - } -private: - Type m_type; - std::string m_typeName; -}; - - -using errorSourceLocationInfo = std::pair; - -class SecondarySourceLocation -{ -public: - SecondarySourceLocation& append(std::string const& _errMsg, SourceLocation const& _sourceLocation) - { - infos.push_back(std::make_pair(_errMsg, _sourceLocation)); - return *this; - } - /// Limits the number of secondary source locations to 32 and appends a notice to the - /// error message. - void limitSize(std::string& _message) - { - size_t occurrences = infos.size(); - if (occurrences > 32) - { - infos.resize(32); - _message += " Truncated from " + std::to_string(occurrences) + " to the first 32 occurrences."; - } - } - - std::vector infos; -}; - - -using errinfo_sourceLocation = boost::error_info; -using errinfo_secondarySourceLocation = boost::error_info; - -} -} diff --git a/libsolidity/interface/GasEstimator.h b/libsolidity/interface/GasEstimator.h index ea94d988..214a3e58 100644 --- a/libsolidity/interface/GasEstimator.h +++ b/libsolidity/interface/GasEstimator.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include #include diff --git a/libsolidity/interface/SourceReferenceFormatter.cpp b/libsolidity/interface/SourceReferenceFormatter.cpp index 865907e2..9e2c988e 100644 --- a/libsolidity/interface/SourceReferenceFormatter.cpp +++ b/libsolidity/interface/SourceReferenceFormatter.cpp @@ -21,8 +21,8 @@ */ #include -#include -#include +#include +#include using namespace std; diff --git a/libsolidity/interface/SourceReferenceFormatter.h b/libsolidity/interface/SourceReferenceFormatter.h index a32babdc..281a4bdc 100644 --- a/libsolidity/interface/SourceReferenceFormatter.h +++ b/libsolidity/interface/SourceReferenceFormatter.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include namespace dev { diff --git a/libsolidity/interface/Version.cpp b/libsolidity/interface/Version.cpp index b5f68ce8..b785d557 100644 --- a/libsolidity/interface/Version.cpp +++ b/libsolidity/interface/Version.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include using namespace dev; diff --git a/libsolidity/parsing/DocStringParser.cpp b/libsolidity/parsing/DocStringParser.cpp index d9588e5c..17a7b691 100644 --- a/libsolidity/parsing/DocStringParser.cpp +++ b/libsolidity/parsing/DocStringParser.cpp @@ -1,7 +1,7 @@ #include -#include -#include +#include +#include #include #include diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index b17dad9a..f070620d 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -22,11 +22,11 @@ #include #include -#include +#include #include -#include +#include #include -#include +#include using namespace std; diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index fa974171..f20f01c5 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -23,7 +23,7 @@ #pragma once #include -#include +#include namespace dev { diff --git a/libsolidity/parsing/ParserBase.cpp b/libsolidity/parsing/ParserBase.cpp deleted file mode 100644 index 1d4cb1e2..00000000 --- a/libsolidity/parsing/ParserBase.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - 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 . -*/ -/** - * @author Christian - * @date 2016 - * Solidity parser shared functionality. - */ - -#include -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::solidity; - -std::shared_ptr const& ParserBase::sourceName() const -{ - return m_scanner->sourceName(); -} - -int ParserBase::position() const -{ - return m_scanner->currentLocation().start; -} - -int ParserBase::endPosition() const -{ - return m_scanner->currentLocation().end; -} - -Token ParserBase::currentToken() const -{ - return m_scanner->currentToken(); -} - -Token ParserBase::peekNextToken() const -{ - return m_scanner->peekNextToken(); -} - -std::string ParserBase::currentLiteral() const -{ - return m_scanner->currentLiteral(); -} - -Token ParserBase::advance() -{ - return m_scanner->next(); -} - -void ParserBase::expectToken(Token _value, bool _advance) -{ - Token tok = m_scanner->currentToken(); - if (tok != _value) - { - auto tokenName = [this](Token _token) - { - if (_token == Token::Identifier) - return string("identifier"); - else if (_token == Token::EOS) - return string("end of source"); - else if (TokenTraits::isReservedKeyword(_token)) - return string("reserved keyword '") + TokenTraits::friendlyName(_token) + "'"; - else if (TokenTraits::isElementaryTypeName(_token)) //for the sake of accuracy in reporting - { - ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken(); - return string("'") + elemTypeName.toString() + "'"; - } - else - return string("'") + TokenTraits::friendlyName(_token) + "'"; - }; - - fatalParserError(string("Expected ") + tokenName(_value) + string(" but got ") + tokenName(tok)); - } - if (_advance) - m_scanner->next(); -} - -void ParserBase::increaseRecursionDepth() -{ - m_recursionDepth++; - if (m_recursionDepth >= 2560) - fatalParserError("Maximum recursion depth reached during parsing."); -} - -void ParserBase::decreaseRecursionDepth() -{ - solAssert(m_recursionDepth > 0, ""); - m_recursionDepth--; -} - -void ParserBase::parserError(string const& _description) -{ - m_errorReporter.parserError(SourceLocation(position(), endPosition(), sourceName()), _description); -} - -void ParserBase::fatalParserError(string const& _description) -{ - m_errorReporter.fatalParserError(SourceLocation(position(), endPosition(), sourceName()), _description); -} diff --git a/libsolidity/parsing/ParserBase.h b/libsolidity/parsing/ParserBase.h deleted file mode 100644 index e01f37d8..00000000 --- a/libsolidity/parsing/ParserBase.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - 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 . -*/ -/** - * @author Christian - * @date 2016 - * Solidity parser shared functionality. - */ - -#pragma once - -#include -#include - -namespace dev -{ -namespace solidity -{ - -class ErrorReporter; -class Scanner; - -class ParserBase -{ -public: - explicit ParserBase(ErrorReporter& errorReporter): m_errorReporter(errorReporter) {} - - std::shared_ptr const& sourceName() const; - -protected: - /// Utility class that creates an error and throws an exception if the - /// recursion depth is too deep. - class RecursionGuard - { - public: - explicit RecursionGuard(ParserBase& _parser): m_parser(_parser) - { - m_parser.increaseRecursionDepth(); - } - ~RecursionGuard() { m_parser.decreaseRecursionDepth(); } - private: - ParserBase& m_parser; - }; - - /// Start position of the current token - int position() const; - /// End position of the current token - int endPosition() const; - - ///@{ - ///@name Helper functions - /// If current token value is not _value, throw exception otherwise advance token. - void expectToken(Token _value, bool _advance = true); - Token currentToken() const; - Token peekNextToken() const; - std::string currentLiteral() const; - Token advance(); - ///@} - - /// Increases the recursion depth and throws an exception if it is too deep. - void increaseRecursionDepth(); - void decreaseRecursionDepth(); - - /// Creates a @ref ParserError and annotates it with the current position and the - /// given @a _description. - void parserError(std::string const& _description); - - /// Creates a @ref ParserError and annotates it with the current position and the - /// given @a _description. Throws the FatalError. - void fatalParserError(std::string const& _description); - - std::shared_ptr m_scanner; - /// The reference to the list of errors and warning to add errors/warnings during parsing - ErrorReporter& m_errorReporter; - /// Current recursion depth during parsing. - size_t m_recursionDepth = 0; -}; - -} -} diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp deleted file mode 100644 index e9dad2ad..00000000 --- a/libsolidity/parsing/Scanner.cpp +++ /dev/null @@ -1,920 +0,0 @@ -/* - 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 . - - This file is derived from the file "scanner.cc", which was part of the - V8 project. The original copyright header follows: - - Copyright 2006-2012, the V8 project authors. All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/** - * @author Christian - * @date 2014 - * Solidity scanner. - */ - -#include -#include -#include -#include - -using namespace std; - -namespace dev -{ -namespace solidity -{ - -namespace -{ -bool isDecimalDigit(char c) -{ - return '0' <= c && c <= '9'; -} -bool isHexDigit(char c) -{ - return isDecimalDigit(c) - || ('a' <= c && c <= 'f') - || ('A' <= c && c <= 'F'); -} -bool isLineTerminator(char c) -{ - return c == '\n'; -} -bool isWhiteSpace(char c) -{ - return c == ' ' || c == '\n' || c == '\t' || c == '\r'; -} -bool isIdentifierStart(char c) -{ - return c == '_' || c == '$' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); -} -bool isIdentifierPart(char c) -{ - return isIdentifierStart(c) || isDecimalDigit(c); -} -int hexValue(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - else if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - else return -1; -} -} // end anonymous namespace - - - -/// Scoped helper for literal recording. Automatically drops the literal -/// if aborting the scanning before it's complete. -enum LiteralType { - LITERAL_TYPE_STRING, - LITERAL_TYPE_NUMBER, // not really different from string type in behaviour - LITERAL_TYPE_COMMENT -}; - -class LiteralScope -{ -public: - explicit LiteralScope(Scanner* _self, enum LiteralType _type): m_type(_type) - , m_scanner(_self) - , m_complete(false) - { - if (_type == LITERAL_TYPE_COMMENT) - m_scanner->m_nextSkippedComment.literal.clear(); - else - m_scanner->m_nextToken.literal.clear(); - } - ~LiteralScope() - { - if (!m_complete) - { - if (m_type == LITERAL_TYPE_COMMENT) - m_scanner->m_nextSkippedComment.literal.clear(); - else - m_scanner->m_nextToken.literal.clear(); - } - } - void complete() { m_complete = true; } - -private: - enum LiteralType m_type; - Scanner* m_scanner; - bool m_complete; -}; // end of LiteralScope class - - -void Scanner::reset(CharStream const& _source, string const& _sourceName) -{ - m_source = _source; - m_sourceName = make_shared(_sourceName); - reset(); -} - -void Scanner::reset() -{ - m_source.reset(); - m_char = m_source.get(); - skipWhitespace(); - scanToken(); - next(); -} - -bool Scanner::scanHexByte(char& o_scannedByte) -{ - char x = 0; - for (int i = 0; i < 2; i++) - { - int d = hexValue(m_char); - if (d < 0) - { - rollback(i); - return false; - } - x = x * 16 + d; - advance(); - } - o_scannedByte = x; - return true; -} - -bool Scanner::scanUnicode(unsigned & o_codepoint) -{ - unsigned x = 0; - for (int i = 0; i < 4; i++) - { - int d = hexValue(m_char); - if (d < 0) - { - rollback(i); - return false; - } - x = x * 16 + d; - advance(); - } - o_codepoint = x; - return true; -} - -// This supports codepoints between 0000 and FFFF. -void Scanner::addUnicodeAsUTF8(unsigned codepoint) -{ - if (codepoint <= 0x7f) - addLiteralChar(codepoint); - else if (codepoint <= 0x7ff) - { - addLiteralChar(0xc0 | (codepoint >> 6)); - addLiteralChar(0x80 | (codepoint & 0x3f)); - } - else - { - addLiteralChar(0xe0 | (codepoint >> 12)); - addLiteralChar(0x80 | ((codepoint >> 6) & 0x3f)); - addLiteralChar(0x80 | (codepoint & 0x3f)); - } -} - -// Ensure that tokens can be stored in a byte. -BOOST_STATIC_ASSERT(TokenTraits::count() <= 0x100); - -Token Scanner::next() -{ - m_currentToken = m_nextToken; - m_skippedComment = m_nextSkippedComment; - scanToken(); - - return m_currentToken.token; -} - -Token Scanner::selectToken(char _next, Token _then, Token _else) -{ - advance(); - if (m_char == _next) - return selectToken(_then); - else - return _else; -} - -bool Scanner::skipWhitespace() -{ - int const startPosition = sourcePos(); - while (isWhiteSpace(m_char)) - advance(); - // Return whether or not we skipped any characters. - return sourcePos() != startPosition; -} - -void Scanner::skipWhitespaceExceptUnicodeLinebreak() -{ - while (isWhiteSpace(m_char) && !isUnicodeLinebreak()) - advance(); -} - -Token Scanner::skipSingleLineComment() -{ - // Line terminator is not part of the comment. If it is a - // non-ascii line terminator, it will result in a parser error. - while (!isUnicodeLinebreak()) - if (!advance()) break; - - return Token::Whitespace; -} - -Token Scanner::scanSingleLineDocComment() -{ - LiteralScope literal(this, LITERAL_TYPE_COMMENT); - advance(); //consume the last '/' at /// - - skipWhitespaceExceptUnicodeLinebreak(); - - while (!isSourcePastEndOfInput()) - { - if (isLineTerminator(m_char)) - { - // check if next line is also a documentation comment - skipWhitespace(); - if (!m_source.isPastEndOfInput(3) && - m_source.get(0) == '/' && - m_source.get(1) == '/' && - m_source.get(2) == '/') - { - addCommentLiteralChar('\n'); - m_char = m_source.advanceAndGet(3); - } - else - break; // next line is not a documentation comment, we are done - - } - else if (isUnicodeLinebreak()) - // Any line terminator that is not '\n' is considered to end the - // comment. - break; - addCommentLiteralChar(m_char); - advance(); - } - literal.complete(); - return Token::CommentLiteral; -} - -Token Scanner::skipMultiLineComment() -{ - advance(); - while (!isSourcePastEndOfInput()) - { - char ch = m_char; - advance(); - - // If we have reached the end of the multi-line comment, we - // consume the '/' and insert a whitespace. This way all - // multi-line comments are treated as whitespace. - if (ch == '*' && m_char == '/') - { - m_char = ' '; - return Token::Whitespace; - } - } - // Unterminated multi-line comment. - return Token::Illegal; -} - -Token Scanner::scanMultiLineDocComment() -{ - LiteralScope literal(this, LITERAL_TYPE_COMMENT); - bool endFound = false; - bool charsAdded = false; - - while (isWhiteSpace(m_char) && !isLineTerminator(m_char)) - advance(); - - while (!isSourcePastEndOfInput()) - { - //handle newlines in multline comments - if (isLineTerminator(m_char)) - { - skipWhitespace(); - if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '*') - { // it is unknown if this leads to the end of the comment - addCommentLiteralChar('*'); - advance(); - } - else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) != '/') - { // skip first '*' in subsequent lines - if (charsAdded) - addCommentLiteralChar('\n'); - m_char = m_source.advanceAndGet(2); - } - else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/') - { // if after newline the comment ends, don't insert the newline - m_char = m_source.advanceAndGet(2); - endFound = true; - break; - } - else if (charsAdded) - addCommentLiteralChar('\n'); - } - - if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/') - { - m_char = m_source.advanceAndGet(2); - endFound = true; - break; - } - addCommentLiteralChar(m_char); - charsAdded = true; - advance(); - } - literal.complete(); - if (!endFound) - return Token::Illegal; - else - return Token::CommentLiteral; -} - -Token Scanner::scanSlash() -{ - int firstSlashPosition = sourcePos(); - advance(); - if (m_char == '/') - { - if (!advance()) /* double slash comment directly before EOS */ - return Token::Whitespace; - else if (m_char == '/') - { - // doxygen style /// comment - Token comment; - m_nextSkippedComment.location.start = firstSlashPosition; - comment = scanSingleLineDocComment(); - m_nextSkippedComment.location.end = sourcePos(); - m_nextSkippedComment.token = comment; - return Token::Whitespace; - } - else - return skipSingleLineComment(); - } - else if (m_char == '*') - { - // doxygen style /** natspec comment - if (!advance()) /* slash star comment before EOS */ - return Token::Illegal; - else if (m_char == '*') - { - advance(); //consume the last '*' at /** - - // "/**/" - if (m_char == '/') - { - advance(); //skip the closing slash - return Token::Whitespace; - } - // we actually have a multiline documentation comment - Token comment; - m_nextSkippedComment.location.start = firstSlashPosition; - comment = scanMultiLineDocComment(); - m_nextSkippedComment.location.end = sourcePos(); - m_nextSkippedComment.token = comment; - if (comment == Token::Illegal) - return Token::Illegal; - else - return Token::Whitespace; - } - else - return skipMultiLineComment(); - } - else if (m_char == '=') - return selectToken(Token::AssignDiv); - else - return Token::Div; -} - -void Scanner::scanToken() -{ - m_nextToken.literal.clear(); - m_nextToken.extendedTokenInfo = make_tuple(0, 0); - m_nextSkippedComment.literal.clear(); - m_nextSkippedComment.extendedTokenInfo = make_tuple(0, 0); - - Token token; - // M and N are for the purposes of grabbing different type sizes - unsigned m; - unsigned n; - do - { - // Remember the position of the next token - m_nextToken.location.start = sourcePos(); - switch (m_char) - { - case '"': - case '\'': - token = scanString(); - break; - case '<': - // < <= << <<= - advance(); - if (m_char == '=') - token = selectToken(Token::LessThanOrEqual); - else if (m_char == '<') - token = selectToken('=', Token::AssignShl, Token::SHL); - else - token = Token::LessThan; - break; - case '>': - // > >= >> >>= >>> >>>= - advance(); - if (m_char == '=') - token = selectToken(Token::GreaterThanOrEqual); - else if (m_char == '>') - { - // >> >>= >>> >>>= - advance(); - if (m_char == '=') - token = selectToken(Token::AssignSar); - else if (m_char == '>') - token = selectToken('=', Token::AssignShr, Token::SHR); - else - token = Token::SAR; - } - else - token = Token::GreaterThan; - break; - case '=': - // = == => - advance(); - if (m_char == '=') - token = selectToken(Token::Equal); - else if (m_char == '>') - token = selectToken(Token::Arrow); - else - token = Token::Assign; - break; - case '!': - // ! != - advance(); - if (m_char == '=') - token = selectToken(Token::NotEqual); - else - token = Token::Not; - break; - case '+': - // + ++ += - advance(); - if (m_char == '+') - token = selectToken(Token::Inc); - else if (m_char == '=') - token = selectToken(Token::AssignAdd); - else - token = Token::Add; - break; - case '-': - // - -- -= - advance(); - if (m_char == '-') - token = selectToken(Token::Dec); - else if (m_char == '=') - token = selectToken(Token::AssignSub); - else - token = Token::Sub; - break; - case '*': - // * ** *= - advance(); - if (m_char == '*') - token = selectToken(Token::Exp); - else if (m_char == '=') - token = selectToken(Token::AssignMul); - else - token = Token::Mul; - break; - case '%': - // % %= - token = selectToken('=', Token::AssignMod, Token::Mod); - break; - case '/': - // / // /* /= - token = scanSlash(); - break; - case '&': - // & && &= - advance(); - if (m_char == '&') - token = selectToken(Token::And); - else if (m_char == '=') - token = selectToken(Token::AssignBitAnd); - else - token = Token::BitAnd; - break; - case '|': - // | || |= - advance(); - if (m_char == '|') - token = selectToken(Token::Or); - else if (m_char == '=') - token = selectToken(Token::AssignBitOr); - else - token = Token::BitOr; - break; - case '^': - // ^ ^= - token = selectToken('=', Token::AssignBitXor, Token::BitXor); - break; - case '.': - // . Number - advance(); - if (isDecimalDigit(m_char)) - token = scanNumber('.'); - else - token = Token::Period; - break; - case ':': - token = selectToken(Token::Colon); - break; - case ';': - token = selectToken(Token::Semicolon); - break; - case ',': - token = selectToken(Token::Comma); - break; - case '(': - token = selectToken(Token::LParen); - break; - case ')': - token = selectToken(Token::RParen); - break; - case '[': - token = selectToken(Token::LBrack); - break; - case ']': - token = selectToken(Token::RBrack); - break; - case '{': - token = selectToken(Token::LBrace); - break; - case '}': - token = selectToken(Token::RBrace); - break; - case '?': - token = selectToken(Token::Conditional); - break; - case '~': - token = selectToken(Token::BitNot); - break; - default: - if (isIdentifierStart(m_char)) - { - tie(token, m, n) = scanIdentifierOrKeyword(); - - // Special case for hexadecimal literals - if (token == Token::Hex) - { - // reset - m = 0; - n = 0; - - // Special quoted hex string must follow - if (m_char == '"' || m_char == '\'') - token = scanHexString(); - else - token = Token::IllegalHex; - } - } - else if (isDecimalDigit(m_char)) - token = scanNumber(); - else if (skipWhitespace()) - token = Token::Whitespace; - else if (isSourcePastEndOfInput()) - token = Token::EOS; - else - token = selectToken(Token::Illegal); - break; - } - // Continue scanning for tokens as long as we're just skipping - // whitespace. - } - while (token == Token::Whitespace); - m_nextToken.location.end = sourcePos(); - m_nextToken.token = token; - m_nextToken.extendedTokenInfo = make_tuple(m, n); -} - -bool Scanner::scanEscape() -{ - char c = m_char; - advance(); - // Skip escaped newlines. - if (isLineTerminator(c)) - return true; - switch (c) - { - case '\'': // fall through - case '"': // fall through - case '\\': - break; - case 'b': - c = '\b'; - break; - case 'f': - c = '\f'; - break; - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case 't': - c = '\t'; - break; - case 'v': - c = '\v'; - break; - case 'u': - { - unsigned codepoint; - if (!scanUnicode(codepoint)) - return false; - addUnicodeAsUTF8(codepoint); - return true; - } - case 'x': - if (!scanHexByte(c)) - return false; - break; - default: - return false; - } - - addLiteralChar(c); - return true; -} - -bool Scanner::isUnicodeLinebreak() -{ - if (0x0a <= m_char && m_char <= 0x0d) - // line feed, vertical tab, form feed, carriage return - return true; - else if (!m_source.isPastEndOfInput(1) && uint8_t(m_source.get(0)) == 0xc2 && uint8_t(m_source.get(1)) == 0x85) - // NEL - U+0085, C2 85 in utf8 - return true; - else if (!m_source.isPastEndOfInput(2) && uint8_t(m_source.get(0)) == 0xe2 && uint8_t(m_source.get(1)) == 0x80 && ( - uint8_t(m_source.get(2)) == 0xa8 || uint8_t(m_source.get(2)) == 0xa9 - )) - // LS - U+2028, E2 80 A8 in utf8 - // PS - U+2029, E2 80 A9 in utf8 - return true; - else - return false; -} - -Token Scanner::scanString() -{ - char const quote = m_char; - advance(); // consume quote - LiteralScope literal(this, LITERAL_TYPE_STRING); - while (m_char != quote && !isSourcePastEndOfInput() && !isUnicodeLinebreak()) - { - char c = m_char; - advance(); - if (c == '\\') - { - if (isSourcePastEndOfInput() || !scanEscape()) - return Token::Illegal; - } - else - addLiteralChar(c); - } - if (m_char != quote) - return Token::Illegal; - literal.complete(); - advance(); // consume quote - return Token::StringLiteral; -} - -Token Scanner::scanHexString() -{ - char const quote = m_char; - advance(); // consume quote - LiteralScope literal(this, LITERAL_TYPE_STRING); - while (m_char != quote && !isSourcePastEndOfInput()) - { - char c = m_char; - if (!scanHexByte(c)) - return Token::IllegalHex; - addLiteralChar(c); - } - if (m_char != quote) - return Token::IllegalHex; - literal.complete(); - advance(); // consume quote - return Token::StringLiteral; -} - -// Parse for regex [:digit:]+(_[:digit:]+)* -void Scanner::scanDecimalDigits() -{ - // MUST begin with a decimal digit. - if (!isDecimalDigit(m_char)) - return; - - // May continue with decimal digit or underscore for grouping. - do addLiteralCharAndAdvance(); - while (!m_source.isPastEndOfInput() && (isDecimalDigit(m_char) || m_char == '_')); - - // Defer further validation of underscore to SyntaxChecker. -} - -Token Scanner::scanNumber(char _charSeen) -{ - enum { DECIMAL, HEX, BINARY } kind = DECIMAL; - LiteralScope literal(this, LITERAL_TYPE_NUMBER); - if (_charSeen == '.') - { - // we have already seen a decimal point of the float - addLiteralChar('.'); - if (m_char == '_') - return Token::Illegal; - scanDecimalDigits(); // we know we have at least one digit - } - else - { - solAssert(_charSeen == 0, ""); - // if the first character is '0' we must check for octals and hex - if (m_char == '0') - { - addLiteralCharAndAdvance(); - // either 0, 0exxx, 0Exxx, 0.xxx or a hex number - if (m_char == 'x') - { - // hex number - kind = HEX; - addLiteralCharAndAdvance(); - if (!isHexDigit(m_char)) - return Token::Illegal; // we must have at least one hex digit after 'x' - - while (isHexDigit(m_char) || m_char == '_') // We keep the underscores for later validation - addLiteralCharAndAdvance(); - } - else if (isDecimalDigit(m_char)) - // We do not allow octal numbers - return Token::Illegal; - } - // Parse decimal digits and allow trailing fractional part. - if (kind == DECIMAL) - { - scanDecimalDigits(); // optional - if (m_char == '.') - { - if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_') - { - // Assume the input may be a floating point number with leading '_' in fraction part. - // Recover by consuming it all but returning `Illegal` right away. - addLiteralCharAndAdvance(); // '.' - addLiteralCharAndAdvance(); // '_' - scanDecimalDigits(); - } - if (m_source.isPastEndOfInput() || !isDecimalDigit(m_source.get(1))) - { - // A '.' has to be followed by a number. - literal.complete(); - return Token::Number; - } - addLiteralCharAndAdvance(); - scanDecimalDigits(); - } - } - } - // scan exponent, if any - if (m_char == 'e' || m_char == 'E') - { - solAssert(kind != HEX, "'e'/'E' must be scanned as part of the hex number"); - if (kind != DECIMAL) - return Token::Illegal; - else if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_') - { - // Recover from wrongly placed underscore as delimiter in literal with scientific - // notation by consuming until the end. - addLiteralCharAndAdvance(); // 'e' - addLiteralCharAndAdvance(); // '_' - scanDecimalDigits(); - literal.complete(); - return Token::Number; - } - // scan exponent - addLiteralCharAndAdvance(); // 'e' | 'E' - if (m_char == '+' || m_char == '-') - addLiteralCharAndAdvance(); - if (!isDecimalDigit(m_char)) - return Token::Illegal; // we must have at least one decimal digit after 'e'/'E' - scanDecimalDigits(); - } - // The source character immediately following a numeric literal must - // not be an identifier start or a decimal digit; see ECMA-262 - // section 7.8.3, page 17 (note that we read only one decimal digit - // if the value is 0). - if (isDecimalDigit(m_char) || isIdentifierStart(m_char)) - return Token::Illegal; - literal.complete(); - return Token::Number; -} - -tuple Scanner::scanIdentifierOrKeyword() -{ - solAssert(isIdentifierStart(m_char), ""); - LiteralScope literal(this, LITERAL_TYPE_STRING); - addLiteralCharAndAdvance(); - // Scan the rest of the identifier characters. - while (isIdentifierPart(m_char)) //get full literal - addLiteralCharAndAdvance(); - literal.complete(); - return TokenTraits::fromIdentifierOrKeyword(m_nextToken.literal); -} - -char CharStream::advanceAndGet(size_t _chars) -{ - if (isPastEndOfInput()) - return 0; - m_position += _chars; - if (isPastEndOfInput()) - return 0; - return m_source[m_position]; -} - -char CharStream::rollback(size_t _amount) -{ - solAssert(m_position >= _amount, ""); - m_position -= _amount; - return get(); -} - -string CharStream::lineAtPosition(int _position) const -{ - // if _position points to \n, it returns the line before the \n - using size_type = string::size_type; - size_type searchStart = min(m_source.size(), _position); - if (searchStart > 0) - searchStart--; - size_type lineStart = m_source.rfind('\n', searchStart); - if (lineStart == string::npos) - lineStart = 0; - else - lineStart++; - return m_source.substr(lineStart, min(m_source.find('\n', lineStart), - m_source.size()) - lineStart); -} - -tuple CharStream::translatePositionToLineColumn(int _position) const -{ - using size_type = string::size_type; - size_type searchPosition = min(m_source.size(), _position); - int lineNumber = count(m_source.begin(), m_source.begin() + searchPosition, '\n'); - size_type lineStart; - if (searchPosition == 0) - lineStart = 0; - else - { - lineStart = m_source.rfind('\n', searchPosition - 1); - lineStart = lineStart == string::npos ? 0 : lineStart + 1; - } - return tuple(lineNumber, searchPosition - lineStart); -} - - -} -} diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h deleted file mode 100644 index 14eeb66e..00000000 --- a/libsolidity/parsing/Scanner.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - 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 . - - This file is derived from the file "scanner.h", which was part of the - V8 project. The original copyright header follows: - - Copyright 2006-2012, the V8 project authors. All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/** - * @author Christian - * @date 2014 - * Solidity scanner. - */ - -#pragma once - -#include -#include -#include -#include - -namespace dev -{ -namespace solidity -{ - - -class AstRawString; -class AstValueFactory; -class ParserRecorder; - -class CharStream -{ -public: - CharStream(): m_position(0) {} - explicit CharStream(std::string const& _source): m_source(_source), m_position(0) {} - int position() const { return m_position; } - bool isPastEndOfInput(size_t _charsForward = 0) const { return (m_position + _charsForward) >= m_source.size(); } - char get(size_t _charsForward = 0) const { return m_source[m_position + _charsForward]; } - char advanceAndGet(size_t _chars = 1); - char rollback(size_t _amount); - - void reset() { m_position = 0; } - - std::string const& source() const { return m_source; } - - ///@{ - ///@name Error printing helper functions - /// Functions that help pretty-printing parse errors - /// Do only use in error cases, they are quite expensive. - std::string lineAtPosition(int _position) const; - std::tuple translatePositionToLineColumn(int _position) const; - ///@} - -private: - std::string m_source; - size_t m_position; -}; - - - -class Scanner -{ - friend class LiteralScope; -public: - - explicit Scanner(CharStream const& _source = CharStream(), std::string const& _sourceName = "") { reset(_source, _sourceName); } - - std::string source() const { return m_source.source(); } - - /// Resets the scanner as if newly constructed with _source and _sourceName as input. - void reset(CharStream const& _source, std::string const& _sourceName); - /// Resets scanner to the start of input. - void reset(); - - /// @returns the next token and advances input - Token next(); - - ///@{ - ///@name Information about the current token - - /// @returns the current token - Token currentToken() const - { - return m_currentToken.token; - } - ElementaryTypeNameToken currentElementaryTypeNameToken() const - { - unsigned firstSize; - unsigned secondSize; - std::tie(firstSize, secondSize) = m_currentToken.extendedTokenInfo; - return ElementaryTypeNameToken(m_currentToken.token, firstSize, secondSize); - } - - SourceLocation currentLocation() const { return m_currentToken.location; } - std::string const& currentLiteral() const { return m_currentToken.literal; } - std::tuple const& currentTokenInfo() const { return m_currentToken.extendedTokenInfo; } - ///@} - - ///@{ - ///@name Information about the current comment token - - SourceLocation currentCommentLocation() const { return m_skippedComment.location; } - std::string const& currentCommentLiteral() const { return m_skippedComment.literal; } - /// Called by the parser during FunctionDefinition parsing to clear the current comment - void clearCurrentCommentLiteral() { m_skippedComment.literal.clear(); } - - ///@} - - ///@{ - ///@name Information about the next token - - /// @returns the next token without advancing input. - Token peekNextToken() const { return m_nextToken.token; } - SourceLocation peekLocation() const { return m_nextToken.location; } - std::string const& peekLiteral() const { return m_nextToken.literal; } - ///@} - - std::shared_ptr const& sourceName() const { return m_sourceName; } - - ///@{ - ///@name Error printing helper functions - /// Functions that help pretty-printing parse errors - /// Do only use in error cases, they are quite expensive. - std::string lineAtPosition(int _position) const { return m_source.lineAtPosition(_position); } - std::tuple translatePositionToLineColumn(int _position) const { return m_source.translatePositionToLineColumn(_position); } - std::string sourceAt(SourceLocation const& _location) const - { - solAssert(!_location.isEmpty(), ""); - solAssert(m_sourceName && _location.sourceName, ""); - solAssert(*m_sourceName == *_location.sourceName, ""); - return m_source.source().substr(_location.start, _location.end - _location.start); - } - ///@} - -private: - /// Used for the current and look-ahead token and comments - struct TokenDesc - { - Token token; - SourceLocation location; - std::string literal; - std::tuple extendedTokenInfo; - }; - - ///@{ - ///@name Literal buffer support - inline void addLiteralChar(char c) { m_nextToken.literal.push_back(c); } - inline void addCommentLiteralChar(char c) { m_nextSkippedComment.literal.push_back(c); } - inline void addLiteralCharAndAdvance() { addLiteralChar(m_char); advance(); } - void addUnicodeAsUTF8(unsigned codepoint); - ///@} - - bool advance() { m_char = m_source.advanceAndGet(); return !m_source.isPastEndOfInput(); } - void rollback(int _amount) { m_char = m_source.rollback(_amount); } - - inline Token selectToken(Token _tok) { advance(); return _tok; } - /// If the next character is _next, advance and return _then, otherwise return _else. - inline Token selectToken(char _next, Token _then, Token _else); - - bool scanHexByte(char& o_scannedByte); - bool scanUnicode(unsigned& o_codepoint); - - /// Scans a single Solidity token. - void scanToken(); - - /// Skips all whitespace and @returns true if something was skipped. - bool skipWhitespace(); - /// Skips all whitespace that are neither '\r' nor '\n'. - void skipWhitespaceExceptUnicodeLinebreak(); - Token skipSingleLineComment(); - Token skipMultiLineComment(); - - void scanDecimalDigits(); - Token scanNumber(char _charSeen = 0); - std::tuple scanIdentifierOrKeyword(); - - Token scanString(); - Token scanHexString(); - Token scanSingleLineDocComment(); - Token scanMultiLineDocComment(); - /// Scans a slash '/' and depending on the characters returns the appropriate token - Token scanSlash(); - - /// Scans an escape-sequence which is part of a string and adds the - /// decoded character to the current literal. Returns true if a pattern - /// is scanned. - bool scanEscape(); - - /// @returns true iff we are currently positioned at a unicode line break. - bool isUnicodeLinebreak(); - - /// Return the current source position. - int sourcePos() const { return m_source.position(); } - bool isSourcePastEndOfInput() const { return m_source.isPastEndOfInput(); } - - TokenDesc m_skippedComment; // desc for current skipped comment - TokenDesc m_nextSkippedComment; // desc for next skipped comment - - TokenDesc m_currentToken; // desc for current token (as returned by Next()) - TokenDesc m_nextToken; // desc for next token (one token look-ahead) - - CharStream m_source; - std::shared_ptr m_sourceName; - - /// one character look-ahead, equals 0 at end of input - char m_char; -}; - -} -} diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp deleted file mode 100644 index dccd9037..00000000 --- a/libsolidity/parsing/Token.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2006-2012, the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Modifications as part of solidity under the following license: -// -// 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 . - -#include -#include -#include - -using namespace std; - -namespace dev -{ -namespace solidity -{ - -void ElementaryTypeNameToken::assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second) -{ - solAssert(TokenTraits::isElementaryTypeName(_baseType), "Expected elementary type name: " + string(TokenTraits::toString(_baseType))); - if (_baseType == Token::BytesM) - { - solAssert(_second == 0, "There should not be a second size argument to type bytesM."); - solAssert(_first <= 32, "No elementary type bytes" + to_string(_first) + "."); - } - else if (_baseType == Token::UIntM || _baseType == Token::IntM) - { - solAssert(_second == 0, "There should not be a second size argument to type " + string(TokenTraits::toString(_baseType)) + "."); - solAssert( - _first <= 256 && _first % 8 == 0, - "No elementary type " + string(TokenTraits::toString(_baseType)) + to_string(_first) + "." - ); - } - else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN) - { - solAssert( - _first >= 8 && _first <= 256 && _first % 8 == 0 && _second <= 80, - "No elementary type " + string(TokenTraits::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "." - ); - } - m_token = _baseType; - m_firstNumber = _first; - m_secondNumber = _second; -} - -namespace TokenTraits -{ - -char const* toString(Token tok) -{ - switch (tok) - { -#define T(name, string, precedence) case Token::name: return string; - TOKEN_LIST(T, T) -#undef T - default: // Token::NUM_TOKENS: - return ""; - } -} - -char const* name(Token tok) -{ -#define T(name, string, precedence) #name, - static char const* const names[TokenTraits::count()] = { TOKEN_LIST(T, T) }; -#undef T - - solAssert(static_cast(tok) < TokenTraits::count(), ""); - return names[static_cast(tok)]; -} - -std::string friendlyName(Token tok) -{ - char const* ret = toString(tok); - if (ret) - return std::string(ret); - - ret = name(tok); - solAssert(ret != nullptr, ""); - return std::string(ret); -} - -#define T(name, string, precedence) precedence, -int precedence(Token tok) -{ - int8_t const static precs[TokenTraits::count()] = - { - TOKEN_LIST(T, T) - }; - return precs[static_cast(tok)]; -} -#undef T - -int parseSize(string::const_iterator _begin, string::const_iterator _end) -{ - try - { - unsigned int m = boost::lexical_cast(boost::make_iterator_range(_begin, _end)); - return m; - } - catch(boost::bad_lexical_cast const&) - { - return -1; - } -} - -static Token keywordByName(string const& _name) -{ - // The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored - // and keywords to be put inside the keywords variable. -#define KEYWORD(name, string, precedence) {string, Token::name}, -#define TOKEN(name, string, precedence) - static const map keywords({TOKEN_LIST(TOKEN, KEYWORD)}); -#undef KEYWORD -#undef TOKEN - auto it = keywords.find(_name); - return it == keywords.end() ? Token::Identifier : it->second; -} - -tuple fromIdentifierOrKeyword(string const& _literal) -{ - auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit); - if (positionM != _literal.end()) - { - string baseType(_literal.begin(), positionM); - auto positionX = find_if_not(positionM, _literal.end(), ::isdigit); - int m = parseSize(positionM, positionX); - Token keyword = keywordByName(baseType); - if (keyword == Token::Bytes) - { - if (0 < m && m <= 32 && positionX == _literal.end()) - return make_tuple(Token::BytesM, m, 0); - } - else if (keyword == Token::UInt || keyword == Token::Int) - { - if (0 < m && m <= 256 && m % 8 == 0 && positionX == _literal.end()) - { - if (keyword == Token::UInt) - return make_tuple(Token::UIntM, m, 0); - else - return make_tuple(Token::IntM, m, 0); - } - } - else if (keyword == Token::UFixed || keyword == Token::Fixed) - { - if ( - positionM < positionX && - positionX < _literal.end() && - *positionX == 'x' && - all_of(positionX + 1, _literal.end(), ::isdigit) - ) { - int n = parseSize(positionX + 1, _literal.end()); - if ( - 8 <= m && m <= 256 && m % 8 == 0 && - 0 <= n && n <= 80 - ) { - if (keyword == Token::UFixed) - return make_tuple(Token::UFixedMxN, m, n); - else - return make_tuple(Token::FixedMxN, m, n); - } - } - } - return make_tuple(Token::Identifier, 0, 0); - } - - return make_tuple(keywordByName(_literal), 0, 0); -} - -} -} -} diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h deleted file mode 100644 index 81e8dd98..00000000 --- a/libsolidity/parsing/Token.h +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright 2006-2012, the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Modifications as part of solidity under the following license: -// -// 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 . - -#pragma once - -#include -#include -#include -#include - -namespace dev -{ -namespace solidity -{ - -// TOKEN_LIST takes a list of 3 macros M, all of which satisfy the -// same signature M(name, string, precedence), where name is the -// symbolic token name, string is the corresponding syntactic symbol -// (or NULL, for literals), and precedence is the precedence (or 0). -// The parameters are invoked for token categories as follows: -// -// T: Non-keyword tokens -// K: Keyword tokens - -// IGNORE_TOKEN is a convenience macro that can be supplied as -// an argument (at any position) for a TOKEN_LIST call. It does -// nothing with tokens belonging to the respective category. - -#define IGNORE_TOKEN(name, string, precedence) - -#define TOKEN_LIST(T, K) \ - /* End of source indicator. */ \ - T(EOS, "EOS", 0) \ - \ - /* Punctuators (ECMA-262, section 7.7, page 15). */ \ - T(LParen, "(", 0) \ - T(RParen, ")", 0) \ - T(LBrack, "[", 0) \ - T(RBrack, "]", 0) \ - T(LBrace, "{", 0) \ - T(RBrace, "}", 0) \ - T(Colon, ":", 0) \ - T(Semicolon, ";", 0) \ - T(Period, ".", 0) \ - T(Conditional, "?", 3) \ - T(Arrow, "=>", 0) \ - \ - /* Assignment operators. */ \ - /* IsAssignmentOp() relies on this block of enum values being */ \ - /* contiguous and sorted in the same order!*/ \ - T(Assign, "=", 2) \ - /* The following have to be in exactly the same order as the simple binary operators*/ \ - T(AssignBitOr, "|=", 2) \ - T(AssignBitXor, "^=", 2) \ - T(AssignBitAnd, "&=", 2) \ - T(AssignShl, "<<=", 2) \ - T(AssignSar, ">>=", 2) \ - T(AssignShr, ">>>=", 2) \ - T(AssignAdd, "+=", 2) \ - T(AssignSub, "-=", 2) \ - T(AssignMul, "*=", 2) \ - T(AssignDiv, "/=", 2) \ - T(AssignMod, "%=", 2) \ - \ - /* Binary operators sorted by precedence. */ \ - /* IsBinaryOp() relies on this block of enum values */ \ - /* being contiguous and sorted in the same order! */ \ - T(Comma, ",", 1) \ - T(Or, "||", 4) \ - T(And, "&&", 5) \ - T(BitOr, "|", 8) \ - T(BitXor, "^", 9) \ - T(BitAnd, "&", 10) \ - T(SHL, "<<", 11) \ - T(SAR, ">>", 11) \ - T(SHR, ">>>", 11) \ - T(Add, "+", 12) \ - T(Sub, "-", 12) \ - T(Mul, "*", 13) \ - T(Div, "/", 13) \ - T(Mod, "%", 13) \ - T(Exp, "**", 14) \ - \ - /* Compare operators sorted by precedence. */ \ - /* IsCompareOp() relies on this block of enum values */ \ - /* being contiguous and sorted in the same order! */ \ - T(Equal, "==", 6) \ - T(NotEqual, "!=", 6) \ - T(LessThan, "<", 7) \ - T(GreaterThan, ">", 7) \ - T(LessThanOrEqual, "<=", 7) \ - T(GreaterThanOrEqual, ">=", 7) \ - \ - /* Unary operators. */ \ - /* IsUnaryOp() relies on this block of enum values */ \ - /* being contiguous and sorted in the same order! */ \ - T(Not, "!", 0) \ - T(BitNot, "~", 0) \ - T(Inc, "++", 0) \ - T(Dec, "--", 0) \ - K(Delete, "delete", 0) \ - \ - /* Keywords */ \ - K(Anonymous, "anonymous", 0) \ - K(As, "as", 0) \ - K(Assembly, "assembly", 0) \ - K(Break, "break", 0) \ - K(Constant, "constant", 0) \ - K(Constructor, "constructor", 0) \ - K(Continue, "continue", 0) \ - K(Contract, "contract", 0) \ - K(Do, "do", 0) \ - K(Else, "else", 0) \ - K(Enum, "enum", 0) \ - K(Emit, "emit", 0) \ - K(Event, "event", 0) \ - K(External, "external", 0) \ - K(For, "for", 0) \ - K(Function, "function", 0) \ - K(Hex, "hex", 0) \ - K(If, "if", 0) \ - K(Indexed, "indexed", 0) \ - K(Interface, "interface", 0) \ - K(Internal, "internal", 0) \ - K(Import, "import", 0) \ - K(Is, "is", 0) \ - K(Library, "library", 0) \ - K(Mapping, "mapping", 0) \ - K(Memory, "memory", 0) \ - K(Modifier, "modifier", 0) \ - K(New, "new", 0) \ - K(Payable, "payable", 0) \ - K(Public, "public", 0) \ - K(Pragma, "pragma", 0) \ - K(Private, "private", 0) \ - K(Pure, "pure", 0) \ - K(Return, "return", 0) \ - K(Returns, "returns", 0) \ - K(Storage, "storage", 0) \ - K(CallData, "calldata", 0) \ - K(Struct, "struct", 0) \ - K(Throw, "throw", 0) \ - K(Using, "using", 0) \ - K(Var, "var", 0) \ - K(View, "view", 0) \ - K(While, "while", 0) \ - \ - /* Ether subdenominations */ \ - K(SubWei, "wei", 0) \ - K(SubSzabo, "szabo", 0) \ - K(SubFinney, "finney", 0) \ - K(SubEther, "ether", 0) \ - K(SubSecond, "seconds", 0) \ - K(SubMinute, "minutes", 0) \ - K(SubHour, "hours", 0) \ - K(SubDay, "days", 0) \ - K(SubWeek, "weeks", 0) \ - K(SubYear, "years", 0) \ - /* type keywords*/ \ - K(Int, "int", 0) \ - K(UInt, "uint", 0) \ - K(Bytes, "bytes", 0) \ - K(Byte, "byte", 0) \ - K(String, "string", 0) \ - K(Address, "address", 0) \ - K(Bool, "bool", 0) \ - K(Fixed, "fixed", 0) \ - K(UFixed, "ufixed", 0) \ - T(IntM, "intM", 0) \ - T(UIntM, "uintM", 0) \ - T(BytesM, "bytesM", 0) \ - T(FixedMxN, "fixedMxN", 0) \ - T(UFixedMxN, "ufixedMxN", 0) \ - T(TypesEnd, NULL, 0) /* used as type enum end marker */ \ - \ - /* Literals */ \ - K(TrueLiteral, "true", 0) \ - K(FalseLiteral, "false", 0) \ - T(Number, NULL, 0) \ - T(StringLiteral, NULL, 0) \ - T(CommentLiteral, NULL, 0) \ - \ - /* Identifiers (not keywords or future reserved words). */ \ - T(Identifier, NULL, 0) \ - \ - /* Keywords reserved for future use. */ \ - K(Abstract, "abstract", 0) \ - K(After, "after", 0) \ - K(Alias, "alias", 0) \ - K(Apply, "apply", 0) \ - K(Auto, "auto", 0) \ - K(Case, "case", 0) \ - K(Catch, "catch", 0) \ - K(CopyOf, "copyof", 0) \ - K(Default, "default", 0) \ - K(Define, "define", 0) \ - K(Final, "final", 0) \ - K(Immutable, "immutable", 0) \ - K(Implements, "implements", 0) \ - K(In, "in", 0) \ - K(Inline, "inline", 0) \ - K(Let, "let", 0) \ - K(Macro, "macro", 0) \ - K(Match, "match", 0) \ - K(Mutable, "mutable", 0) \ - K(NullLiteral, "null", 0) \ - K(Of, "of", 0) \ - K(Override, "override", 0) \ - K(Partial, "partial", 0) \ - K(Promise, "promise", 0) \ - K(Reference, "reference", 0) \ - K(Relocatable, "relocatable", 0) \ - K(Sealed, "sealed", 0) \ - K(Sizeof, "sizeof", 0) \ - K(Static, "static", 0) \ - K(Supports, "supports", 0) \ - K(Switch, "switch", 0) \ - K(Try, "try", 0) \ - K(Type, "type", 0) \ - K(Typedef, "typedef", 0) \ - K(TypeOf, "typeof", 0) \ - K(Unchecked, "unchecked", 0) \ - \ - /* Illegal token - not able to scan. */ \ - T(Illegal, "ILLEGAL", 0) \ - /* Illegal hex token */ \ - T(IllegalHex, "ILLEGAL_HEX", 0) \ - \ - /* Scanner-internal use only. */ \ - T(Whitespace, NULL, 0) - -// All token values. -// attention! msvc issue: -// http://stackoverflow.com/questions/9567868/compile-errors-after-adding-v8-to-my-project-c2143-c2059 -// @todo: avoid TOKEN_LIST macro -enum class Token : unsigned int { -#define T(name, string, precedence) name, - TOKEN_LIST(T, T) - NUM_TOKENS -#undef T -}; - -namespace TokenTraits -{ - constexpr size_t count() { return static_cast(Token::NUM_TOKENS); } - - // Predicates - constexpr bool isElementaryTypeName(Token tok) { return Token::Int <= tok && tok < Token::TypesEnd; } - constexpr bool isAssignmentOp(Token tok) { return Token::Assign <= tok && tok <= Token::AssignMod; } - constexpr bool isBinaryOp(Token op) { return Token::Comma <= op && op <= Token::Exp; } - constexpr bool isCommutativeOp(Token op) { return op == Token::BitOr || op == Token::BitXor || op == Token::BitAnd || - op == Token::Add || op == Token::Mul || op == Token::Equal || op == Token::NotEqual; } - constexpr bool isArithmeticOp(Token op) { return Token::Add <= op && op <= Token::Exp; } - constexpr bool isCompareOp(Token op) { return Token::Equal <= op && op <= Token::GreaterThanOrEqual; } - - constexpr bool isBitOp(Token op) { return (Token::BitOr <= op && op <= Token::BitAnd) || op == Token::BitNot; } - constexpr bool isBooleanOp(Token op) { return (Token::Or <= op && op <= Token::And) || op == Token::Not; } - constexpr bool isUnaryOp(Token op) { return (Token::Not <= op && op <= Token::Delete) || op == Token::Add || op == Token::Sub; } - constexpr bool isCountOp(Token op) { return op == Token::Inc || op == Token::Dec; } - constexpr bool isShiftOp(Token op) { return (Token::SHL <= op) && (op <= Token::SHR); } - constexpr bool isVariableVisibilitySpecifier(Token op) { return op == Token::Public || op == Token::Private || op == Token::Internal; } - constexpr bool isVisibilitySpecifier(Token op) { return isVariableVisibilitySpecifier(op) || op == Token::External; } - constexpr bool isLocationSpecifier(Token op) { return op == Token::Memory || op == Token::Storage || op == Token::CallData; } - - constexpr bool isStateMutabilitySpecifier(Token op, bool _allowConstant = true) - { - return (op == Token::Constant && _allowConstant) - || op == Token::Pure || op == Token::View || op == Token::Payable; - } - - constexpr bool isEtherSubdenomination(Token op) { return op == Token::SubWei || op == Token::SubSzabo || op == Token::SubFinney || op == Token::SubEther; } - constexpr bool isTimeSubdenomination(Token op) { return op == Token::SubSecond || op == Token::SubMinute || op == Token::SubHour || op == Token::SubDay || op == Token::SubWeek || op == Token::SubYear; } - constexpr bool isReservedKeyword(Token op) { return (Token::Abstract <= op && op <= Token::Unchecked); } - - inline Token AssignmentToBinaryOp(Token op) - { - solAssert(isAssignmentOp(op) && op != Token::Assign, ""); - return static_cast(static_cast(op) + (static_cast(Token::BitOr) - static_cast(Token::AssignBitOr))); - } - - // @returns the precedence > 0 for binary and compare - // operators; returns 0 otherwise. - int precedence(Token tok); - - std::tuple fromIdentifierOrKeyword(std::string const& _literal); - - // @returns a string corresponding to the C++ token name - // (e.g. "LT" for the token LT). - char const* name(Token tok); - - // @returns a string corresponding to the JS token string - // (.e., "<" for the token LT) or NULL if the token doesn't - // have a (unique) string (e.g. an IDENTIFIER). - char const* toString(Token tok); - - std::string friendlyName(Token tok); -} - -inline std::ostream& operator<<(std::ostream& os, Token token) -{ - os << TokenTraits::friendlyName(token); - return os; -} - -class ElementaryTypeNameToken -{ -public: - ElementaryTypeNameToken(Token _token, unsigned const& _firstNumber, unsigned const& _secondNumber) - { - assertDetails(_token, _firstNumber, _secondNumber); - } - - unsigned int firstNumber() const { return m_firstNumber; } - unsigned int secondNumber() const { return m_secondNumber; } - Token token() const { return m_token; } - - ///if tokValue is set to true, then returns the actual token type name, otherwise, returns full type - std::string toString(bool const& tokenValue = false) const - { - std::string name = TokenTraits::toString(m_token); - if (tokenValue || (firstNumber() == 0 && secondNumber() == 0)) - return name; - solAssert(name.size() >= 3, "Token name size should be greater than 3. Should not reach here."); - if (m_token == Token::FixedMxN || m_token == Token::UFixedMxN) - return name.substr(0, name.size() - 3) + std::to_string(m_firstNumber) + "x" + std::to_string(m_secondNumber); - else - return name.substr(0, name.size() - 1) + std::to_string(m_firstNumber); - } - -private: - Token m_token; - unsigned int m_firstNumber; - unsigned int m_secondNumber; - /// throws if type is not properly sized - void assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second); -}; - -} -} diff --git a/libsolidity/parsing/UndefMacros.h b/libsolidity/parsing/UndefMacros.h deleted file mode 100644 index d96e242e..00000000 --- a/libsolidity/parsing/UndefMacros.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - 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 . -*/ -/** @file UndefMacros.h - * @author Lefteris - * @date 2015 - * - * This header should be used to #undef some really evil macros defined by - * windows.h which result in conflict with our Token.h - */ -#pragma once - -#if defined(_MSC_VER) || defined(__MINGW32__) - -#undef DELETE -#undef IN -#undef VOID -#undef THIS -#undef CONST - -// Conflicting define on MinGW in windows.h -// windows.h(19): #define interface struct -#ifdef interface -#undef interface -#endif - -#elif defined(DELETE) || defined(IN) || defined(VOID) || defined(THIS) || defined(CONST) || defined(interface) - -#error "The preceding macros in this header file are reserved for V8's "\ -"TOKEN_LIST. Please add a platform specific define above to undefine "\ -"overlapping macros." - -#endif diff --git a/libyul/backends/evm/EVMAssembly.cpp b/libyul/backends/evm/EVMAssembly.cpp index b37a3231..e4ba37f0 100644 --- a/libyul/backends/evm/EVMAssembly.cpp +++ b/libyul/backends/evm/EVMAssembly.cpp @@ -22,7 +22,7 @@ #include -#include +#include using namespace std; using namespace dev; diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 650a8c0a..23e09756 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index 8243160d..5ebb3bf6 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 844cef90..357d0ab3 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -26,12 +26,12 @@ #include "license.h" #include -#include +#include #include #include #include #include -#include +#include #include #include #include diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index aa49383a..8dc00370 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3b674502..acfc7d00 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,8 @@ file(GLOB contracts_sources "contracts/*.cpp") file(GLOB contracts_headers "contracts/*.h") file(GLOB libdevcore_sources "libdevcore/*.cpp") file(GLOB libdevcore_headers "libdevcore/*.h") +file(GLOB liblangutil_sources "liblangutil/*.cpp") +file(GLOB liblangutil_headers "liblangutil/*.h") file(GLOB libevmasm_sources "libevmasm/*.cpp") file(GLOB libevmasm_headers "libevmasm/*.h") file(GLOB libyul_sources "libyul/*.cpp") @@ -19,6 +21,7 @@ file(GLOB libsolidity_headers "libsolidity/*.h") add_executable(soltest ${sources} ${headers} ${contracts_sources} ${contracts_headers} ${libdevcore_sources} ${libdevcore_headers} + ${liblangutil_sources} ${liblangutil_headers} ${libevmasm_sources} ${libevmasm_headers} ${libyul_sources} ${libyul_headers} ${liblll_sources} ${liblll_headers} diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index d6de95a3..86c1bcca 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/test/Options.cpp b/test/Options.cpp index da08eb37..9f0d6752 100644 --- a/test/Options.cpp +++ b/test/Options.cpp @@ -23,8 +23,8 @@ #include -#include -#include +#include +#include #include #include diff --git a/test/Options.h b/test/Options.h index 0e8a51da..af6f06ee 100644 --- a/test/Options.h +++ b/test/Options.h @@ -19,7 +19,7 @@ #pragma once -#include +#include #include #include diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index 9ac24972..0aae21a7 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include diff --git a/test/libevmasm/SourceLocation.cpp b/test/libevmasm/SourceLocation.cpp deleted file mode 100644 index 764da3cd..00000000 --- a/test/libevmasm/SourceLocation.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - 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 . -*/ -/** - * @author Yoichi Hirai - * @date 2016 - * Unit tests for the SourceLocation class. - */ - -#include - -#include - -namespace dev -{ -namespace solidity -{ -namespace test -{ - -BOOST_AUTO_TEST_SUITE(SourceLocationTest) - -BOOST_AUTO_TEST_CASE(test_fail) -{ - BOOST_CHECK(SourceLocation() == SourceLocation()); - BOOST_CHECK(SourceLocation(0, 3, std::make_shared("sourceA")) != SourceLocation(0, 3, std::make_shared("sourceB"))); - BOOST_CHECK(SourceLocation(0, 3, std::make_shared("source")) == SourceLocation(0, 3, std::make_shared("source"))); - BOOST_CHECK(SourceLocation(3, 7, std::make_shared("source")).contains(SourceLocation(4, 6, std::make_shared("source")))); - BOOST_CHECK(!SourceLocation(3, 7, std::make_shared("sourceA")).contains(SourceLocation(4, 6, std::make_shared("sourceB")))); - BOOST_CHECK(SourceLocation(3, 7, std::make_shared("sourceA")) < SourceLocation(4, 6, std::make_shared("sourceB"))); -} - -BOOST_AUTO_TEST_SUITE_END() - -} -} -} // end namespaces diff --git a/test/liblangutil/SourceLocation.cpp b/test/liblangutil/SourceLocation.cpp new file mode 100644 index 00000000..29cfb6a0 --- /dev/null +++ b/test/liblangutil/SourceLocation.cpp @@ -0,0 +1,50 @@ +/* + 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 . +*/ +/** + * @author Yoichi Hirai + * @date 2016 + * Unit tests for the SourceLocation class. + */ + +#include + +#include + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(SourceLocationTest) + +BOOST_AUTO_TEST_CASE(test_fail) +{ + BOOST_CHECK(SourceLocation() == SourceLocation()); + BOOST_CHECK(SourceLocation(0, 3, std::make_shared("sourceA")) != SourceLocation(0, 3, std::make_shared("sourceB"))); + BOOST_CHECK(SourceLocation(0, 3, std::make_shared("source")) == SourceLocation(0, 3, std::make_shared("source"))); + BOOST_CHECK(SourceLocation(3, 7, std::make_shared("source")).contains(SourceLocation(4, 6, std::make_shared("source")))); + BOOST_CHECK(!SourceLocation(3, 7, std::make_shared("sourceA")).contains(SourceLocation(4, 6, std::make_shared("sourceB")))); + BOOST_CHECK(SourceLocation(3, 7, std::make_shared("sourceA")) < SourceLocation(4, 6, std::make_shared("sourceB"))); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp index 94319985..291ed15a 100644 --- a/test/libsolidity/ABIDecoderTests.cpp +++ b/test/libsolidity/ABIDecoderTests.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index d2125cc7..b6e6cedd 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index ec98026c..dafd1748 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -27,7 +27,7 @@ #include -#include +#include #include diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 5e157678..78fa7bcf 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -22,16 +22,16 @@ #include -#include +#include #include -#include +#include #include #include #include #include #include -#include +#include #include diff --git a/test/libsolidity/ErrorCheck.h b/test/libsolidity/ErrorCheck.h index 8ad81f85..c70a6645 100644 --- a/test/libsolidity/ErrorCheck.h +++ b/test/libsolidity/ErrorCheck.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index dc33d577..abd659b6 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index a9ce6e49..3079e032 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -23,8 +23,8 @@ #include #include -#include -#include +#include +#include #include #include #include diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index 43951f73..b2f4b3c2 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 87646737..041f29a8 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -25,8 +25,8 @@ #include -#include -#include +#include +#include #include diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 12687dd1..ab71a3e0 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include namespace dev diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 309cbf0b..37183279 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -22,14 +22,14 @@ #include -#include +#include #include #include #include #include #include #include -#include +#include #include using namespace std; diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index d77050cb..45191ce1 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include namespace dev diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 5432e9b5..cf5461ba 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -22,9 +22,9 @@ #include #include -#include +#include #include -#include +#include #include #include diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 6965d886..53ec0a4c 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -20,7 +20,7 @@ * Unit tests for the solidity scanner. */ -#include +#include #include using namespace std; diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index 654ce4a0..0f151e66 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index d224bdcd..b351483e 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -25,14 +25,14 @@ #include -#include +#include #include #include #include #include -#include +#include #include diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 3f329d28..3a887176 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 9e257717..57c4d7f0 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -41,12 +41,12 @@ #include #include -#include +#include #include #include #include #include -#include +#include #include #include diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 3e96ef35..df5331f7 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -21,13 +21,13 @@ #include #include #include -#include +#include #include #include #include #include #include -#include +#include #include #include -- cgit