diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e5895b6de..dc05ce18f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include @@ -707,7 +706,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) *_inlineAssembly.annotation().analysisInfo, m_errorReporter, Error::Type::SyntaxError, - yul::EVMDialect::looseAssemblyForEVM(m_evmVersion), + _inlineAssembly.dialect(), identifierAccess ); if (!analyzer.analyze(_inlineAssembly.operations())) diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 9067e13ea..a59dc0b4c 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,11 @@ namespace class AssemblyViewPureChecker: public boost::static_visitor { public: - explicit AssemblyViewPureChecker(std::function _reportMutability): + explicit AssemblyViewPureChecker( + yul::Dialect const& _dialect, + std::function _reportMutability + ): + m_dialect(_dialect), m_reportMutability(_reportMutability) {} void operator()(yul::Label const&) { } @@ -69,6 +74,11 @@ public: } void operator()(yul::FunctionCall const& _funCall) { + if (yul::EVMDialect const* dialect = dynamic_cast(&m_dialect)) + if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name)) + if (fun->instruction) + checkInstruction(_funCall.location, *fun->instruction); + for (auto const& arg: _funCall.arguments) boost::apply_visitor(*this, arg); } @@ -107,7 +117,6 @@ public: } private: - std::function m_reportMutability; void checkInstruction(SourceLocation _location, dev::eth::Instruction _instruction) { if (eth::SemanticInformation::invalidInViewFunctions(_instruction)) @@ -117,6 +126,9 @@ private: else if (eth::SemanticInformation::invalidInPureFunctions(_instruction)) m_reportMutability(StateMutability::View, _location); } + + yul::Dialect const& m_dialect; + std::function m_reportMutability; }; } @@ -223,6 +235,7 @@ void ViewPureChecker::endVisit(Identifier const& _identifier) void ViewPureChecker::endVisit(InlineAssembly const& _inlineAssembly) { AssemblyViewPureChecker{ + _inlineAssembly.dialect(), [=](StateMutability _mutability, SourceLocation const& _location) { reportMutability(_mutability, _location); } }(_inlineAssembly.operations()); } diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index d8229593e..ffdb2a574 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -43,6 +43,7 @@ namespace yul { // Forward-declaration to struct Block; +struct Dialect; } namespace dev @@ -1049,17 +1050,20 @@ public: InlineAssembly( SourceLocation const& _location, ASTPointer const& _docString, + yul::Dialect const& _dialect, std::shared_ptr const& _operations ): - Statement(_location, _docString), m_operations(_operations) {} + Statement(_location, _docString), m_dialect(_dialect), m_operations(_operations) {} void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; + yul::Dialect const& dialect() const { return m_dialect; } yul::Block const& operations() const { return *m_operations; } InlineAssemblyAnnotation& annotation() const override; private: + yul::Dialect const& m_dialect; std::shared_ptr m_operations; }; diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 64c8c779c..539ba85bf 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -35,8 +35,9 @@ namespace yul { - struct AsmAnalysisInfo; - struct Identifier; +struct AsmAnalysisInfo; +struct Identifier; +struct Dialect; } namespace dev diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 3e49173c8..d6e998644 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -217,7 +217,7 @@ bool CompilerStack::parse() string const& path = sourcesToParse[i]; Source& source = m_sources[path]; source.scanner->reset(); - source.ast = Parser(m_errorReporter).parse(source.scanner); + source.ast = Parser(m_errorReporter, m_evmVersion).parse(source.scanner); if (!source.ast) solAssert(!Error::containsOnlyWarnings(m_errorReporter.errors()), "Parser returned null but did not report error."); else diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index cb4525b92..5b5c56523 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -1039,21 +1040,22 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con SourceLocation location{position(), -1, source()}; expectToken(Token::Assembly); + yul::Dialect const& dialect = yul::EVMDialect::looseAssemblyForEVM(m_evmVersion); if (m_scanner->currentToken() == Token::StringLiteral) { if (m_scanner->currentLiteral() != "evmasm") fatalParserError("Only \"evmasm\" supported."); + // This can be used in the future to set the dialect. m_scanner->next(); } - // Using latest EVM Version for now, it will be run again later. - yul::Parser asmParser(m_errorReporter, yul::EVMDialect::looseAssemblyForEVM(EVMVersion{})); + yul::Parser asmParser(m_errorReporter, dialect); shared_ptr block = asmParser.parse(m_scanner, true); if (block == nullptr) BOOST_THROW_EXCEPTION(FatalError()); location.end = block->location.end; - return make_shared(location, _docString, block); + return make_shared(location, _docString, dialect, block); } ASTPointer Parser::parseIfStatement(ASTPointer const& _docString) diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 2468c86ea..51b3b5be4 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -24,6 +24,7 @@ #include #include +#include namespace langutil { @@ -38,7 +39,13 @@ namespace solidity class Parser: public langutil::ParserBase { public: - explicit Parser(langutil::ErrorReporter& _errorReporter): ParserBase(_errorReporter) {} + explicit Parser( + langutil::ErrorReporter& _errorReporter, + langutil::EVMVersion _evmVersion + ): + ParserBase(_errorReporter), + m_evmVersion(_evmVersion) + {} ASTPointer parse(std::shared_ptr const& _scanner); @@ -181,6 +188,7 @@ private: /// Flag that signifies whether '_' is parsed as a PlaceholderStatement or a regular identifier. bool m_insideModifier = false; + langutil::EVMVersion m_evmVersion; }; } diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 375d0c897..36244d576 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -90,19 +90,18 @@ pair createFunction( return {name, f}; } -map createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess, bool _evmOpcodes) +map createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess) { map builtins; - if (_evmOpcodes) - for (auto const& instr: Parser::instructions()) - if ( - !dev::eth::isDupInstruction(instr.second) && - !dev::eth::isSwapInstruction(instr.second) && - instr.second != eth::Instruction::JUMP && - instr.second != eth::Instruction::JUMPI && - _evmVersion.hasOpcode(instr.second) - ) - builtins.emplace(createEVMFunction(instr.first, instr.second)); + for (auto const& instr: Parser::instructions()) + if ( + !dev::eth::isDupInstruction(instr.second) && + !dev::eth::isSwapInstruction(instr.second) && + instr.second != eth::Instruction::JUMP && + instr.second != eth::Instruction::JUMPI && + _evmVersion.hasOpcode(instr.second) + ) + builtins.emplace(createEVMFunction(instr.first, instr.second)); if (_objectAccess) { @@ -167,7 +166,7 @@ EVMDialect::EVMDialect(AsmFlavour _flavour, bool _objectAccess, langutil::EVMVer Dialect{_flavour}, m_objectAccess(_objectAccess), m_evmVersion(_evmVersion), - m_functions(createBuiltins(_evmVersion, _objectAccess, _flavour != AsmFlavour::Loose)) + m_functions(createBuiltins(_evmVersion, _objectAccess)) { } diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 7281fd2eb..db3b395a5 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -57,7 +57,7 @@ eth::AssemblyItems compileContract(std::shared_ptr _sourceCode) { ErrorList errors; ErrorReporter errorReporter(errors); - Parser parser(errorReporter); + Parser parser(errorReporter, dev::test::Options::get().evmVersion()); ASTPointer sourceUnit; BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared(_sourceCode))); BOOST_CHECK(!!sourceUnit); diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 3cdd70f67..607706162 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -102,7 +102,9 @@ bytes compileFirstExpression( { ErrorList errors; ErrorReporter errorReporter(errors); - sourceUnit = Parser(errorReporter).parse(make_shared(CharStream(_sourceCode, ""))); + sourceUnit = Parser(errorReporter, dev::test::Options::get().evmVersion()).parse( + make_shared(CharStream(_sourceCode, "")) + ); if (!sourceUnit) return bytes(); } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 763fda9ca..fe1ce5eda 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -44,7 +44,10 @@ namespace ASTPointer parseText(std::string const& _source, ErrorList& _errors) { ErrorReporter errorReporter(_errors); - ASTPointer sourceUnit = Parser(errorReporter).parse(std::make_shared(CharStream(_source, ""))); + ASTPointer sourceUnit = Parser( + errorReporter, + dev::test::Options::get().evmVersion() + ).parse(std::make_shared(CharStream(_source, ""))); if (!sourceUnit) return ASTPointer(); for (ASTPointer const& node: sourceUnit->nodes())