diff options
47 files changed, 303 insertions, 168 deletions
diff --git a/Changelog.md b/Changelog.md index ff26882d..e6f01553 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.5.1 (unreleased) Language Features: + * Allow public functions to override external functions. Compiler Features: diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index e1a0e91b..bcdfdcd8 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -143,44 +143,6 @@ arguments for you. See `ping.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/45_ping.sol>`_ and `pong.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/45_pong.sol>`_. -When returning a value of say ``uint`` type, is it possible to return an ``undefined`` or "null"-like value? -============================================================================================================ - -This is not possible, because all types use up the full value range. - -You have the option to ``throw`` on error, which will also revert the whole -transaction, which might be a good idea if you ran into an unexpected -situation. - -If you do not want to throw, you can return a pair:: - - pragma solidity >0.4.23 <0.6.0; - - contract C { - uint[] counters; - - function getCounter(uint index) - public - view - returns (uint counter, bool error) { - if (index >= counters.length) - return (0, true); - else - return (counters[index], false); - } - - function checkCounter(uint index) public view { - (uint counter, bool error) = getCounter(index); - if (error) { - // Handle the error - } else { - // Do something with counter. - require(counter > 7, "Invalid counter value"); - } - } - } - - Are comments included with deployed contracts and do they increase deployment gas? ================================================================================== diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index f8de0e8d..2797d8b0 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -115,7 +115,7 @@ Arch Linux also has packages, albeit limited to the latest development version: pacman -S solidity -We distribute the Solidity compiler through Homebrow +We distribute the Solidity compiler through Homebrew as a build-from-source version. Pre-built bottles are currently not supported. diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 9245300b..34ef012e 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -400,7 +400,7 @@ within a word). At the time of expansion, the cost in gas must be paid. Memory i costly the larger it grows (it scales quadratically). The EVM is not a register machine but a stack machine, so all -computations are performed on an data area called the **stack**. It has a maximum size of +computations are performed on a data area called the **stack**. It has a maximum size of 1024 elements and contains words of 256 bits. Access to the stack is limited to the top end in the following way: It is possible to copy one of diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index cc2ba801..017d5b81 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -15,6 +15,10 @@ Statically-sized variables (everything except mapping and dynamically-sized arra - If an elementary type does not fit the remaining part of a storage slot, it is moved to the next storage slot. - Structs and array data always start a new slot and occupy whole slots (but items inside a struct or array are packed tightly according to these rules). +For contracts that use inheritance, the ordering of state variables is determined by the +C3-linearized order of contracts starting with the most base-ward contract. If allowed +by the above rules, state variables from different contracts do share the same storage slot. + .. warning:: When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller diff --git a/docs/types.rst b/docs/types.rst index b84d3222..69c846a6 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -13,6 +13,11 @@ Solidity provides several elementary types which can be combined to form complex In addition, types can interact with each other in expressions containing operators. For a quick reference of the various operators, see :ref:`order`. +The concept of "undefined" or "null" values does not exist in Solidity, but newly +declared variables always have a :ref:`default value<default-value>` dependent +on its type. To handle any unexpected values, you should use the :ref:`revert function<assert-and-require>` to revert the whole transaction, or return a +tuple with a second `bool` value denoting success. + .. index:: ! value type, ! type;value Value Types @@ -273,7 +278,7 @@ Example:: when the call returns. The regular way to interact with other contracts is to call a function on a contract object (``x.f()``). -:: note:: +.. note:: Previous versions of Solidity allowed these functions to receive arbitrary arguments and would also handle a first argument of type ``bytes4`` differently. These edge cases were removed in version 0.5.0. diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index fa7e3f48..01a8bcc6 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -1,7 +1,17 @@ -file(GLOB sources "*.cpp") -file(GLOB headers "*.h") +set(sources + CommonData.cpp + CommonIO.cpp + Exceptions.cpp + IndentedWriter.cpp + JSON.cpp + Keccak256.cpp + StringUtils.cpp + SwarmHash.cpp + UTF8.cpp + Whiskers.cpp +) -add_library(devcore ${sources} ${headers}) +add_library(devcore ${sources}) target_link_libraries(devcore PRIVATE jsoncpp ${Boost_FILESYSTEM_LIBRARIES} ${Boost_REGEX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) target_include_directories(devcore PUBLIC "${CMAKE_SOURCE_DIR}") target_include_directories(devcore SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index 86192c1b..e0e3389a 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -1,5 +1,21 @@ -file(GLOB sources "*.cpp") -file(GLOB headers "*.h") +set(sources + Assembly.cpp + AssemblyItem.cpp + BlockDeduplicator.cpp + CommonSubexpressionEliminator.cpp + ConstantOptimiser.cpp + ControlFlowGraph.cpp + ExpressionClasses.cpp + GasMeter.cpp + Instruction.cpp + JumpdestRemover.cpp + KnownState.cpp + LinkerObject.cpp + PathGasMeter.cpp + PeepholeOptimiser.cpp + SemanticInformation.cpp + SimplificationRules.cpp +) -add_library(evmasm ${sources} ${headers}) +add_library(evmasm ${sources}) target_link_libraries(evmasm PUBLIC devcore) diff --git a/liblangutil/CMakeLists.txt b/liblangutil/CMakeLists.txt index 722ca840..dfcccfce 100644 --- a/liblangutil/CMakeLists.txt +++ b/liblangutil/CMakeLists.txt @@ -1,6 +1,13 @@ # Solidity Commons Library (Solidity related sharing bits between libsolidity and libyul) -file(GLOB sources "*.cpp") -file(GLOB headers "*.h") +set(sources + CharStream.cpp + ErrorReporter.cpp + Exceptions.cpp + ParserBase.cpp + Scanner.cpp + SourceReferenceFormatter.cpp + Token.cpp +) -add_library(langutil ${sources} ${headers}) +add_library(langutil ${sources}) target_link_libraries(langutil PUBLIC devcore) diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp index 3d7527d4..215171b3 100644 --- a/liblangutil/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -53,6 +53,7 @@ #include <liblangutil/Exceptions.h> #include <liblangutil/Scanner.h> #include <algorithm> +#include <ostream> #include <tuple> using namespace std; @@ -100,7 +101,32 @@ int hexValue(char c) } } // end anonymous namespace +std::string to_string(ScannerError _errorCode) +{ + switch (_errorCode) + { + case ScannerError::NoError: return "No error."; + case ScannerError::IllegalToken: return "Invalid token."; + case ScannerError::IllegalHexString: return "Expected even number of hex-nibbles within double-quotes."; + case ScannerError::IllegalHexDigit: return "Hexadecimal digit missing or invalid."; + case ScannerError::IllegalCommentTerminator: return "Expected multi-line comment-terminator."; + case ScannerError::IllegalEscapeSequence: return "Invalid escape sequence."; + case ScannerError::IllegalStringEndQuote: return "Expected string end-quote."; + case ScannerError::IllegalNumberSeparator: return "Invalid use of number separator '_'."; + case ScannerError::IllegalExponent: return "Invalid exponent."; + case ScannerError::IllegalNumberEnd: return "Identifier-start is not allowed at end of a number."; + case ScannerError::OctalNotAllowed: return "Octal numbers not allowed."; + default: + solAssert(false, "Unhandled case in to_string(ScannerError)"); + return ""; + } +} +std::ostream& operator<<(std::ostream& os, ScannerError _errorCode) +{ + os << to_string(_errorCode); + return os; +} /// Scoped helper for literal recording. Automatically drops the literal /// if aborting the scanning before it's complete. @@ -311,7 +337,7 @@ Token Scanner::skipMultiLineComment() } } // Unterminated multi-line comment. - return Token::Illegal; + return setError(ScannerError::IllegalCommentTerminator); } Token Scanner::scanMultiLineDocComment() @@ -362,7 +388,7 @@ Token Scanner::scanMultiLineDocComment() } literal.complete(); if (!endFound) - return Token::Illegal; + return setError(ScannerError::IllegalCommentTerminator); else return Token::CommentLiteral; } @@ -392,7 +418,7 @@ Token Scanner::scanSlash() { // doxygen style /** natspec comment if (!advance()) /* slash star comment before EOS */ - return Token::Illegal; + return setError(ScannerError::IllegalCommentTerminator); else if (m_char == '*') { advance(); //consume the last '*' at /** @@ -410,7 +436,7 @@ Token Scanner::scanSlash() m_nextSkippedComment.location.end = sourcePos(); m_nextSkippedComment.token = comment; if (comment == Token::Illegal) - return Token::Illegal; + return Token::Illegal; // error already set else return Token::Whitespace; } @@ -425,6 +451,7 @@ Token Scanner::scanSlash() void Scanner::scanToken() { + m_nextToken.error = ScannerError::NoError; m_nextToken.literal.clear(); m_nextToken.extendedTokenInfo = make_tuple(0, 0); m_nextSkippedComment.literal.clear(); @@ -610,7 +637,7 @@ void Scanner::scanToken() if (m_char == '"' || m_char == '\'') token = scanHexString(); else - token = Token::IllegalHex; + token = setError(ScannerError::IllegalToken); } } else if (isDecimalDigit(m_char)) @@ -620,7 +647,7 @@ void Scanner::scanToken() else if (isSourcePastEndOfInput()) token = Token::EOS; else - token = selectToken(Token::Illegal); + token = selectErrorToken(ScannerError::IllegalToken); break; } // Continue scanning for tokens as long as we're just skipping @@ -713,13 +740,13 @@ Token Scanner::scanString() if (c == '\\') { if (isSourcePastEndOfInput() || !scanEscape()) - return Token::Illegal; + return setError(ScannerError::IllegalEscapeSequence); } else addLiteralChar(c); } if (m_char != quote) - return Token::Illegal; + return setError(ScannerError::IllegalStringEndQuote); literal.complete(); advance(); // consume quote return Token::StringLiteral; @@ -734,11 +761,14 @@ Token Scanner::scanHexString() { char c = m_char; if (!scanHexByte(c)) - return Token::IllegalHex; + // can only return false if hex-byte is incomplete (only one hex digit instead of two) + return setError(ScannerError::IllegalHexString); addLiteralChar(c); } + if (m_char != quote) - return Token::IllegalHex; + return setError(ScannerError::IllegalStringEndQuote); + literal.complete(); advance(); // consume quote return Token::StringLiteral; @@ -767,7 +797,7 @@ Token Scanner::scanNumber(char _charSeen) // we have already seen a decimal point of the float addLiteralChar('.'); if (m_char == '_') - return Token::Illegal; + return setError(ScannerError::IllegalToken); scanDecimalDigits(); // we know we have at least one digit } else @@ -784,14 +814,14 @@ Token Scanner::scanNumber(char _charSeen) kind = HEX; addLiteralCharAndAdvance(); if (!isHexDigit(m_char)) - return Token::Illegal; // we must have at least one hex digit after 'x' + return setError(ScannerError::IllegalHexDigit); // 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; + return setError(ScannerError::OctalNotAllowed); } // Parse decimal digits and allow trailing fractional part. if (kind == DECIMAL) @@ -823,7 +853,7 @@ Token Scanner::scanNumber(char _charSeen) { solAssert(kind != HEX, "'e'/'E' must be scanned as part of the hex number"); if (kind != DECIMAL) - return Token::Illegal; + return setError(ScannerError::IllegalExponent); else if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_') { // Recover from wrongly placed underscore as delimiter in literal with scientific @@ -838,8 +868,8 @@ Token Scanner::scanNumber(char _charSeen) 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' + if (!isDecimalDigit(m_char)) // we must have at least one decimal digit after 'e'/'E' + return setError(ScannerError::IllegalExponent); scanDecimalDigits(); } // The source character immediately following a numeric literal must @@ -847,7 +877,7 @@ Token Scanner::scanNumber(char _charSeen) // 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; + return setError(ScannerError::IllegalNumberEnd); literal.complete(); return Token::Number; } diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index da5e3dfb..d01e71e2 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -57,6 +57,7 @@ #include <liblangutil/SourceLocation.h> #include <libdevcore/Common.h> #include <libdevcore/CommonData.h> +#include <iosfwd> namespace langutil { @@ -65,6 +66,26 @@ class AstRawString; class AstValueFactory; class ParserRecorder; +enum class ScannerError +{ + NoError, + + IllegalToken, + IllegalHexString, + IllegalHexDigit, + IllegalCommentTerminator, + IllegalEscapeSequence, + IllegalStringEndQuote, + IllegalNumberSeparator, + IllegalExponent, + IllegalNumberEnd, + + OctalNotAllowed, +}; + +std::string to_string(ScannerError _errorCode); +std::ostream& operator<<(std::ostream& os, ScannerError _errorCode); + class Scanner { friend class LiteralScope; @@ -100,6 +121,10 @@ public: SourceLocation currentLocation() const { return m_currentToken.location; } std::string const& currentLiteral() const { return m_currentToken.literal; } std::tuple<unsigned, unsigned> const& currentTokenInfo() const { return m_currentToken.extendedTokenInfo; } + + /// Retrieves the last error that occurred during lexical analysis. + /// @note If no error occurred, the value is undefined. + ScannerError currentError() const noexcept { return m_currentToken.error; } ///@} ///@{ @@ -139,12 +164,19 @@ public: ///@} private: + inline Token setError(ScannerError _error) noexcept + { + m_nextToken.error = _error; + return Token::Illegal; + } + /// Used for the current and look-ahead token and comments struct TokenDesc { Token token; SourceLocation location; std::string literal; + ScannerError error = ScannerError::NoError; std::tuple<unsigned, unsigned> extendedTokenInfo; }; @@ -159,6 +191,7 @@ private: bool advance() { m_char = m_source.advanceAndGet(); return !m_source.isPastEndOfInput(); } void rollback(int _amount) { m_char = m_source.rollback(_amount); } + inline Token selectErrorToken(ScannerError _err) { advance(); return setError(_err); } 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); diff --git a/libsolidity/interface/SourceReferenceFormatter.cpp b/liblangutil/SourceReferenceFormatter.cpp index d727afbe..58a65521 100644 --- a/libsolidity/interface/SourceReferenceFormatter.cpp +++ b/liblangutil/SourceReferenceFormatter.cpp @@ -20,18 +20,14 @@ * Formatting functions for errors referencing positions and locations in the source. */ -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <liblangutil/Scanner.h> #include <liblangutil/Exceptions.h> using namespace std; +using namespace dev; using namespace langutil; -namespace dev -{ -namespace solidity -{ - void SourceReferenceFormatter::printSourceLocation(SourceLocation const* _location) { if (!_location || !_location->sourceName) @@ -103,7 +99,7 @@ void SourceReferenceFormatter::printSourceName(SourceLocation const* _location) } void SourceReferenceFormatter::printExceptionInformation( - Exception const& _exception, + dev::Exception const& _exception, string const& _name ) { @@ -131,6 +127,3 @@ void SourceReferenceFormatter::printExceptionInformation( m_stream << endl; } } - -} -} diff --git a/libsolidity/interface/SourceReferenceFormatter.h b/liblangutil/SourceReferenceFormatter.h index 7dea5254..0ef3ca00 100644 --- a/libsolidity/interface/SourceReferenceFormatter.h +++ b/liblangutil/SourceReferenceFormatter.h @@ -26,21 +26,15 @@ #include <sstream> #include <functional> -namespace langutil -{ -struct SourceLocation; -class Scanner; -} - namespace dev { - struct Exception; // forward +} -namespace solidity +namespace langutil { - -class CompilerStack; // forward +struct SourceLocation; +class Scanner; class SourceReferenceFormatter { @@ -57,10 +51,10 @@ public: /// Prints source location if it is given. void printSourceLocation(langutil::SourceLocation const* _location); - void printExceptionInformation(Exception const& _exception, std::string const& _name); + void printExceptionInformation(dev::Exception const& _exception, std::string const& _name); static std::string formatExceptionInformation( - Exception const& _exception, + dev::Exception const& _exception, std::string const& _name, ScannerFromSourceNameFun const& _scannerFromSourceName ) @@ -80,4 +74,3 @@ private: }; } -} diff --git a/liblangutil/Token.h b/liblangutil/Token.h index d997b138..f832fdf7 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -263,8 +263,6 @@ namespace langutil \ /* Illegal token - not able to scan. */ \ T(Illegal, "ILLEGAL", 0) \ - /* Illegal hex token */ \ - T(IllegalHex, "ILLEGAL_HEX", 0) \ \ /* Scanner-internal use only. */ \ T(Whitespace, nullptr, 0) diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index 4cdc073a..9566c62f 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -1,5 +1,9 @@ -file(GLOB sources "*.cpp") -file(GLOB headers "*.h") +set(sources + CodeFragment.cpp + Compiler.cpp + CompilerState.cpp + Parser.cpp +) -add_library(lll ${sources} ${headers}) +add_library(lll ${sources}) target_link_libraries(lll PUBLIC evmasm devcore) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index c40087f0..d2e0c854 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,14 +1,59 @@ # Until we have a clear separation, libyul has to be included here -file(GLOB_RECURSE sources "*.cpp") -file(GLOB_RECURSE headers "*.h") +set(sources + analysis/ConstantEvaluator.cpp + analysis/ControlFlowAnalyzer.cpp + analysis/ControlFlowBuilder.cpp + analysis/ControlFlowGraph.cpp + analysis/DeclarationContainer.cpp + analysis/DocStringAnalyser.cpp + analysis/GlobalContext.cpp + analysis/NameAndTypeResolver.cpp + analysis/PostTypeChecker.cpp + analysis/ReferencesResolver.cpp + analysis/SemVerHandler.cpp + analysis/StaticAnalyzer.cpp + analysis/SyntaxChecker.cpp + analysis/TypeChecker.cpp + analysis/ViewPureChecker.cpp + ast/AST.cpp + ast/ASTAnnotations.cpp + ast/ASTJsonConverter.cpp + ast/ASTPrinter.cpp + ast/Types.cpp + codegen/ABIFunctions.cpp + codegen/ArrayUtils.cpp + codegen/Compiler.cpp + codegen/CompilerContext.cpp + codegen/CompilerUtils.cpp + codegen/ContractCompiler.cpp + codegen/ExpressionCompiler.cpp + codegen/LValue.cpp + formal/SMTChecker.cpp + formal/SMTLib2Interface.cpp + formal/SMTPortfolio.cpp + formal/SSAVariable.cpp + formal/SymbolicTypes.cpp + formal/SymbolicVariables.cpp + formal/VariableUsage.cpp + interface/ABI.cpp + interface/AssemblyStack.cpp + interface/CompilerStack.cpp + interface/GasEstimator.cpp + interface/Natspec.cpp + interface/StandardCompiler.cpp + interface/Version.cpp + parsing/DocStringParser.cpp + parsing/Parser.cpp +) find_package(Z3 QUIET) if (${Z3_FOUND}) include_directories(${Z3_INCLUDE_DIR}) add_definitions(-DHAVE_Z3) message("Z3 SMT solver found. This enables optional SMT checking with Z3.") + set(z3_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp") else() - list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp") + set(z3_SRCS) endif() find_package(CVC4 QUIET) @@ -16,8 +61,9 @@ if (${CVC4_FOUND}) include_directories(${CVC4_INCLUDE_DIR}) add_definitions(-DHAVE_CVC4) message("CVC4 SMT solver found. This enables optional SMT checking with CVC4.") + set(cvc4_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp") else() - list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp") + set(cvc4_SRCS) endif() if (NOT (${Z3_FOUND} OR ${CVC4_FOUND})) @@ -25,7 +71,7 @@ if (NOT (${Z3_FOUND} OR ${CVC4_FOUND})) \nPlease install Z3 or CVC4 or remove the option disabling them (USE_Z3, USE_CVC4).") endif() -add_library(solidity ${sources} ${headers}) +add_library(solidity ${sources} ${z3_SRCS} ${cvc4_SRCS}) target_link_libraries(solidity PUBLIC yul evmasm langutil devcore ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}) if (${Z3_FOUND}) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4e63875b..d503b9ec 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -400,42 +400,39 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr } } -void TypeChecker::checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super) +void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super) { - FunctionType functionType(function); - FunctionType superType(super); + FunctionType functionType(_function); + FunctionType superType(_super); if (!functionType.hasEqualParameterTypes(superType)) return; - if (!function.annotation().superFunction) - function.annotation().superFunction = &super; + if (!_function.annotation().superFunction) + _function.annotation().superFunction = &_super; - if (function.visibility() != super.visibility()) + if (_function.visibility() != _super.visibility()) { - // visibility is enforced to be external in interfaces, but a contract can override that with public - if ( - super.inContractKind() == ContractDefinition::ContractKind::Interface && - function.inContractKind() != ContractDefinition::ContractKind::Interface && - function.visibility() == FunctionDefinition::Visibility::Public - ) - return; - overrideError(function, super, "Overriding function visibility differs."); + // Visibility change from external to public is fine. + // Any other change is disallowed. + if (!( + _super.visibility() == FunctionDefinition::Visibility::External && + _function.visibility() == FunctionDefinition::Visibility::Public + )) + overrideError(_function, _super, "Overriding function visibility differs."); } - - else if (function.stateMutability() != super.stateMutability()) + else if (_function.stateMutability() != _super.stateMutability()) overrideError( - function, - super, + _function, + _super, "Overriding function changes state mutability from \"" + - stateMutabilityToString(super.stateMutability()) + + stateMutabilityToString(_super.stateMutability()) + "\" to \"" + - stateMutabilityToString(function.stateMutability()) + + stateMutabilityToString(_function.stateMutability()) + "\"." ); - else if (functionType != superType) - overrideError(function, super, "Overriding function return types differ."); + overrideError(_function, _super, "Overriding function return types differ."); } void TypeChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 0eab75aa..102e43e9 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -442,10 +442,11 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition if (!function->isVisibleAsLibraryMember() || seenFunctions.count(function)) continue; seenFunctions.insert(function); - FunctionType funType(*function, false); - if (auto fun = funType.asMemberFunction(true, true)) - if (_type.isImplicitlyConvertibleTo(*fun->selfType())) - members.push_back(MemberList::Member(function->name(), fun, function)); + if (function->parameters().empty()) + continue; + FunctionTypePointer fun = FunctionType(*function, false).asCallableFunction(true, true); + if (_type.isImplicitlyConvertibleTo(*fun->selfType())) + members.push_back(MemberList::Member(function->name(), fun, function)); } } return members; @@ -1970,7 +1971,7 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _con for (auto const& it: m_contract.interfaceFunctions()) members.push_back(MemberList::Member( it.second->declaration().name(), - it.second->asMemberFunction(m_contract.isLibrary()), + it.second->asCallableFunction(m_contract.isLibrary()), &it.second->declaration() )); } @@ -3059,10 +3060,10 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con ); } -FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound) const +FunctionTypePointer FunctionType::asCallableFunction(bool _inLibrary, bool _bound) const { - if (_bound && m_parameterTypes.empty()) - return FunctionTypePointer(); + if (_bound) + solAssert(!m_parameterTypes.empty(), ""); TypePointers parameterTypes; for (auto const& t: m_parameterTypes) @@ -3201,7 +3202,7 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current if (function->isVisibleAsLibraryMember()) members.push_back(MemberList::Member( function->name(), - FunctionType(*function).asMemberFunction(true), + FunctionType(*function).asCallableFunction(true), function )); if (isBase) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 482d6735..953aa557 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1154,14 +1154,13 @@ public: /// of the parameters to false. TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const; - /// @returns a copy of this function type where all return parameters of dynamic size are - /// removed and the location of reference types is changed from CallData to Memory. - /// This is needed if external functions are called on other contracts, as they cannot return - /// dynamic values. - /// Returns empty shared pointer on a failure. Namely, if a bound function has no parameters. + /// @returns a copy of this function type where the location of reference types is changed + /// from CallData to Memory. This is the type that would be used when the function is + /// called, as opposed to the parameter types that are available inside the function body. + /// Also supports variants to be used for library or bound calls. /// @param _inLibrary if true, uses DelegateCall as location. - /// @param _bound if true, the arguments are placed as `arg1.functionName(arg2, ..., argn)`. - FunctionTypePointer asMemberFunction(bool _inLibrary, bool _bound = false) const; + /// @param _bound if true, the function type is set to be bound. + FunctionTypePointer asCallableFunction(bool _inLibrary, bool _bound = false) const; private: static TypePointers parseElementaryTypeVector(strings const& _types); diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index d1bf29fc..2fd62de2 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -25,7 +25,7 @@ #include <libsolidity/ast/AST.h> #include <libsolidity/codegen/Compiler.h> #include <libsolidity/interface/Version.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <libyul/AsmParser.h> #include <libyul/AsmCodeGen.h> #include <libyul/AsmAnalysis.h> @@ -414,7 +414,7 @@ FunctionDefinition const& CompilerContext::resolveVirtualFunction( if ( function->name() == name && !function->isConstructor() && - FunctionType(*function).hasEqualParameterTypes(functionType) + FunctionType(*function).asCallableFunction(false)->hasEqualParameterTypes(functionType) ) return *function; solAssert(false, "Super function " + name + " not found."); diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index bf33b789..4a32d9f3 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -21,7 +21,7 @@ */ #include <libsolidity/interface/StandardCompiler.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <libsolidity/ast/ASTJsonConverter.h> #include <libevmasm/Instruction.h> #include <libdevcore/JSON.h> diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index ffe2be83..3f4a015b 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1555,8 +1555,8 @@ ASTPointer<Expression> Parser::parsePrimaryExpression() expression = nodeFactory.createNode<TupleExpression>(components, isArray); break; } - case Token::IllegalHex: - fatalParserError("Expected even number of hex-nibbles within double-quotes."); + case Token::Illegal: + fatalParserError(to_string(m_scanner->currentError())); break; default: if (TokenTraits::isElementaryTypeName(token)) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index b523f052..7f64d8ac 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -34,7 +34,7 @@ #include <liblangutil/Exceptions.h> #include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/StandardCompiler.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <libsolidity/interface/GasEstimator.h> #include <libsolidity/interface/AssemblyStack.h> diff --git a/test/libsolidity/TestCase.cpp b/test/TestCase.cpp index 17972269..e9e2c9f2 100644 --- a/test/libsolidity/TestCase.cpp +++ b/test/TestCase.cpp @@ -15,7 +15,7 @@ along with solidity. If not, see <http://www.gnu.org/licenses/>. */ -#include <test/libsolidity/TestCase.h> +#include <test/TestCase.h> #include <boost/algorithm/string.hpp> #include <boost/algorithm/string/predicate.hpp> diff --git a/test/libsolidity/TestCase.h b/test/TestCase.h index 3c05ae4e..3c05ae4e 100644 --- a/test/libsolidity/TestCase.h +++ b/test/TestCase.h diff --git a/test/libsolidity/ASTJSONTest.h b/test/libsolidity/ASTJSONTest.h index 9760ef66..dcdaf221 100644 --- a/test/libsolidity/ASTJSONTest.h +++ b/test/libsolidity/ASTJSONTest.h @@ -18,7 +18,7 @@ #pragma once #include <test/libsolidity/FormattedScope.h> -#include <test/libsolidity/TestCase.h> +#include <test/TestCase.h> #include <iosfwd> #include <string> diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 12d63cb7..bd24115c 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -23,7 +23,7 @@ #include <test/Options.h> #include <libsolidity/interface/CompilerStack.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <libsolidity/ast/AST.h> diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index 61f16c0f..601948bc 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -26,7 +26,7 @@ #include <libevmasm/PathGasMeter.h> #include <libsolidity/ast/AST.h> #include <libsolidity/interface/GasEstimator.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> using namespace std; using namespace langutil; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e591432a..e9667483 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -14062,6 +14062,21 @@ BOOST_AUTO_TEST_CASE(flipping_sign_tests) ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } +BOOST_AUTO_TEST_CASE(external_public_override) +{ + char const* sourceCode = R"( + contract A { + function f() external returns (uint) { return 1; } + } + contract B is A { + function f() public returns (uint) { return 2; } + function g() public returns (uint) { return f(); } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(2)); +} BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index d43e994d..cedbf51a 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -28,7 +28,7 @@ #include <libsolidity/interface/CompilerStack.h> #include <liblangutil/Exceptions.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> namespace dev { @@ -73,7 +73,7 @@ public: if (!m_compiler.compile()) { auto scannerFromSourceName = [&](std::string const& _sourceName) -> langutil::Scanner const& { return m_compiler.scanner(_sourceName); }; - SourceReferenceFormatter formatter(std::cerr, scannerFromSourceName); + langutil::SourceReferenceFormatter formatter(std::cerr, scannerFromSourceName); for (auto const& error: m_compiler.errors()) formatter.printExceptionInformation( diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 2d164ae3..02d91d32 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -88,6 +88,7 @@ BOOST_AUTO_TEST_CASE(string_escape_illegal) Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalEscapeSequence); BOOST_CHECK_EQUAL(scanner.currentLiteral(), ""); // TODO recovery from illegal tokens should be improved BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); @@ -486,28 +487,32 @@ BOOST_AUTO_TEST_CASE(invalid_short_hex_literal) { Scanner scanner(CharStream("{ hex\"00112233F\"")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); } BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_space) { Scanner scanner(CharStream("{ hex\"00112233FF \"")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); } BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_wrong_quotes) { Scanner scanner(CharStream("{ hex\"00112233FF'")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); } BOOST_AUTO_TEST_CASE(invalid_hex_literal_nonhex_string) { Scanner scanner(CharStream("{ hex\"hello\"")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); } // COMMENTS diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index d286f934..12c14087 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -19,7 +19,7 @@ #include <test/libsolidity/AnalysisFramework.h> #include <test/libsolidity/FormattedScope.h> -#include <test/libsolidity/TestCase.h> +#include <test/TestCase.h> #include <liblangutil/Exceptions.h> #include <iosfwd> diff --git a/test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol b/test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol new file mode 100644 index 00000000..3d0394f5 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol @@ -0,0 +1,7 @@ +contract A { + function f() external pure {} +} +contract B is A { + function f() public pure { + } +} diff --git a/test/libsolidity/syntaxTests/inheritance/super_on_external.sol b/test/libsolidity/syntaxTests/inheritance/super_on_external.sol new file mode 100644 index 00000000..21f3b1c2 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/super_on_external.sol @@ -0,0 +1,10 @@ +contract A { + function f() external pure {} +} +contract B is A { + function f() public pure { + super.f(); + } +} +// ---- +// TypeError: (106-113): Member "f" not found or not visible after argument-dependent lookup in contract super B. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol index 715913de..b44d09e3 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol @@ -7,4 +7,4 @@ contract C { } // ---- // ParserError: (72-73): Literal, identifier or instruction expected. -// ParserError: (72-73): Expected primary expression. +// ParserError: (72-73): Octal numbers not allowed. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol index cb9eb3fa..6f0c7df7 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol @@ -4,4 +4,3 @@ contract C { } // ---- // DeclarationError: (17-66): Function with same name and arguments defined twice. -// TypeError: (17-66): Overriding function visibility differs. diff --git a/test/libsolidity/syntaxTests/parsing/invalid_fixed_conversion_leading_zeroes_check.sol b/test/libsolidity/syntaxTests/parsing/invalid_fixed_conversion_leading_zeroes_check.sol index fb267ba3..352b5f8f 100644 --- a/test/libsolidity/syntaxTests/parsing/invalid_fixed_conversion_leading_zeroes_check.sol +++ b/test/libsolidity/syntaxTests/parsing/invalid_fixed_conversion_leading_zeroes_check.sol @@ -4,4 +4,4 @@ contract test { } } // ---- -// ParserError: (44-47): Expected primary expression. +// ParserError: (44-47): Identifier-start is not allowed at end of a number. diff --git a/test/libsolidity/syntaxTests/string/string_new_line.sol b/test/libsolidity/syntaxTests/string/string_new_line.sol index da2240f7..4cbc71a5 100644 --- a/test/libsolidity/syntaxTests/string/string_new_line.sol +++ b/test/libsolidity/syntaxTests/string/string_new_line.sol @@ -6,4 +6,4 @@ contract test { } } // ---- -// ParserError: (100-112): Expected primary expression. +// ParserError: (100-112): Expected string end-quote. diff --git a/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol b/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol index 3eaba6af..fba53a03 100644 --- a/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol +++ b/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol @@ -5,4 +5,4 @@ contract test { } } // ---- -// ParserError: (100-109): Expected primary expression.
\ No newline at end of file +// ParserError: (100-109): Expected string end-quote. diff --git a/test/libsolidity/syntaxTests/string/string_unterminated.sol b/test/libsolidity/syntaxTests/string/string_unterminated.sol index 3291781e..e893f4b1 100644 --- a/test/libsolidity/syntaxTests/string/string_unterminated.sol +++ b/test/libsolidity/syntaxTests/string/string_unterminated.sol @@ -4,4 +4,4 @@ contract test { } } // ---- -// ParserError: (100-112): Expected primary expression.
\ No newline at end of file +// ParserError: (100-112): Expected string end-quote. diff --git a/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol b/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol index e7be50d2..b100396b 100644 --- a/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol +++ b/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol @@ -1,4 +1,4 @@ contract test { function f() pure public { "abc\ // ---- -// ParserError: (47-53): Expected primary expression.
\ No newline at end of file +// ParserError: (47-53): Expected string end-quote. diff --git a/test/libsolidity/syntaxTests/unicode_escape_literals.sol b/test/libsolidity/syntaxTests/unicode_escape_literals.sol index a340487b..4415d493 100644 --- a/test/libsolidity/syntaxTests/unicode_escape_literals.sol +++ b/test/libsolidity/syntaxTests/unicode_escape_literals.sol @@ -28,4 +28,4 @@ contract test { } // ---- -// ParserError: (678-681): Expected primary expression. +// ParserError: (678-681): Invalid escape sequence. diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index d7785287..2e70d086 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -23,7 +23,7 @@ #include <test/Options.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <libyul/optimiser/Disambiguator.h> #include <libyul/AsmParser.h> diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 9c2da493..c857d8a5 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -43,7 +43,7 @@ #include <libyul/AsmPrinter.h> #include <libyul/AsmParser.h> #include <libyul/AsmAnalysis.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <liblangutil/ErrorReporter.h> #include <liblangutil/Scanner.h> diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 72c4299f..90026e24 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -17,7 +17,7 @@ #pragma once -#include <test/libsolidity/TestCase.h> +#include <test/TestCase.h> namespace langutil { diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index a0fbe140..736212fc 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -4,7 +4,7 @@ target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_L add_executable(yulopti yulopti.cpp) target_link_libraries(yulopti PRIVATE solidity ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_SYSTEM_LIBRARIES}) -add_executable(isoltest isoltest.cpp ../Options.cpp ../Common.cpp ../libsolidity/TestCase.cpp ../libsolidity/SyntaxTest.cpp +add_executable(isoltest isoltest.cpp ../Options.cpp ../Common.cpp ../TestCase.cpp ../libsolidity/SyntaxTest.cpp ../libsolidity/AnalysisFramework.cpp ../libsolidity/SolidityExecutionFramework.cpp ../ExecutionFramework.cpp ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp ../libsolidity/SMTCheckerJSONTest.cpp ../libyul/YulOptimizerTest.cpp) target_link_libraries(isoltest PRIVATE libsolc solidity evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 7a147137..5a8a5106 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -27,7 +27,7 @@ #include <libyul/AsmData.h> #include <libyul/AsmParser.h> #include <libyul/AsmPrinter.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <libyul/optimiser/BlockFlattener.h> #include <libyul/optimiser/Disambiguator.h> |