2017-05-03 08:30:01 +00:00
/*
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 < http : //www.gnu.org/licenses/>.
*/
/**
* @ date 2017
2018-06-12 18:55:14 +00:00
* Unit tests for parsing Yul .
2017-05-03 08:30:01 +00:00
*/
2020-01-14 16:48:17 +00:00
# include <test/Common.h>
2017-05-03 08:30:01 +00:00
2017-05-24 16:34:19 +00:00
# include <test/libsolidity/ErrorCheck.h>
2018-12-04 10:23:28 +00:00
# include <test/libyul/Common.h>
2017-05-24 16:34:19 +00:00
2021-04-27 14:53:04 +00:00
# include <libyul/AST.h>
2018-11-23 10:18:57 +00:00
# include <libyul/AsmParser.h>
2020-01-16 17:06:27 +00:00
# include <libyul/AsmPrinter.h>
2018-11-23 10:18:57 +00:00
# include <libyul/AsmAnalysis.h>
# include <libyul/AsmAnalysisInfo.h>
2018-12-04 10:23:28 +00:00
# include <libyul/Dialect.h>
2018-11-14 13:59:30 +00:00
# include <liblangutil/ErrorReporter.h>
2017-05-03 08:30:01 +00:00
# include <boost/algorithm/string/replace.hpp>
2020-01-14 14:55:31 +00:00
# include <boost/test/unit_test.hpp>
2017-05-03 08:30:01 +00:00
# include <memory>
2019-10-28 10:39:30 +00:00
# include <optional>
# include <string>
2017-05-03 08:30:01 +00:00
using namespace std ;
2019-12-23 15:50:30 +00:00
using namespace solidity ;
using namespace solidity : : util ;
using namespace solidity : : langutil ;
2017-05-03 08:30:01 +00:00
2021-09-08 16:47:57 +00:00
BOOST_TEST_DONT_PRINT_LOG_VALUE ( ErrorId )
BOOST_TEST_DONT_PRINT_LOG_VALUE ( Error : : Type )
2019-12-23 15:50:30 +00:00
namespace solidity : : yul : : test
2017-05-03 08:30:01 +00:00
{
namespace
{
2020-01-16 17:06:27 +00:00
shared_ptr < Block > parse ( string const & _source , Dialect const & _dialect , ErrorReporter & errorReporter )
2017-05-03 08:30:01 +00:00
{
try
{
2021-07-14 10:53:39 +00:00
auto stream = CharStream ( _source , " " ) ;
2021-06-29 12:38:59 +00:00
map < unsigned , shared_ptr < string const > > indicesToSourceNames ;
indicesToSourceNames [ 0 ] = make_shared < string const > ( " source0 " ) ;
indicesToSourceNames [ 1 ] = make_shared < string const > ( " source1 " ) ;
2021-06-16 10:38:34 +00:00
auto parserResult = yul : : Parser (
errorReporter ,
_dialect ,
2021-06-29 12:38:59 +00:00
move ( indicesToSourceNames )
2021-08-03 13:36:00 +00:00
) . parse ( stream ) ;
2017-05-03 08:30:01 +00:00
if ( parserResult )
2017-05-25 00:28:47 +00:00
{
2018-11-21 11:42:34 +00:00
yul : : AsmAnalysisInfo analysisInfo ;
2020-01-16 17:06:27 +00:00
if ( yul : : AsmAnalyzer (
2018-02-23 10:42:53 +00:00
analysisInfo ,
errorReporter ,
2018-12-03 17:06:07 +00:00
_dialect
2020-01-16 17:06:27 +00:00
) . analyze ( * parserResult ) )
return parserResult ;
2017-05-25 00:28:47 +00:00
}
2017-05-03 08:30:01 +00:00
}
catch ( FatalError const & )
{
BOOST_FAIL ( " Fatal error leaked. " ) ;
}
2020-01-16 17:06:27 +00:00
return { } ;
2017-05-03 08:30:01 +00:00
}
2019-10-28 10:39:30 +00:00
std : : optional < Error > parseAndReturnFirstError ( string const & _source , Dialect const & _dialect , bool _allowWarnings = true )
2017-05-03 08:30:01 +00:00
{
ErrorList errors ;
2017-05-11 13:26:35 +00:00
ErrorReporter errorReporter ( errors ) ;
2018-12-03 17:06:07 +00:00
if ( ! parse ( _source , _dialect , errorReporter ) )
2017-05-03 08:30:01 +00:00
{
2018-12-04 10:23:58 +00:00
BOOST_REQUIRE ( ! errors . empty ( ) ) ;
BOOST_CHECK_EQUAL ( errors . size ( ) , 1 ) ;
2017-05-03 08:30:01 +00:00
return * errors . front ( ) ;
}
else
{
// If success is true, there might still be an error in the assembly stage.
if ( _allowWarnings & & Error : : containsOnlyWarnings ( errors ) )
return { } ;
else if ( ! errors . empty ( ) )
{
if ( ! _allowWarnings )
BOOST_CHECK_EQUAL ( errors . size ( ) , 1 ) ;
return * errors . front ( ) ;
}
}
return { } ;
}
2020-01-29 17:14:03 +00:00
bool successParse ( std : : string const & _source , Dialect const & _dialect = Dialect : : yulDeprecated ( ) , bool _allowWarnings = true )
2017-05-03 08:30:01 +00:00
{
2018-12-03 17:06:07 +00:00
return ! parseAndReturnFirstError ( _source , _dialect , _allowWarnings ) ;
2017-05-03 08:30:01 +00:00
}
2020-01-29 17:14:03 +00:00
Error expectError ( std : : string const & _source , Dialect const & _dialect = Dialect : : yulDeprecated ( ) , bool _allowWarnings = false )
2017-05-03 08:30:01 +00:00
{
2018-12-03 17:06:07 +00:00
auto error = parseAndReturnFirstError ( _source , _dialect , _allowWarnings ) ;
2017-05-03 08:30:01 +00:00
BOOST_REQUIRE ( error ) ;
return * error ;
}
}
2018-12-03 17:06:07 +00:00
# define CHECK_ERROR_DIALECT(text, typ, substring, dialect) \
2017-05-03 08:30:01 +00:00
do \
{ \
2018-12-03 17:06:07 +00:00
Error err = expectError ( ( text ) , dialect , false ) ; \
2017-05-03 08:30:01 +00:00
BOOST_CHECK ( err . type ( ) = = ( Error : : Type : : typ ) ) ; \
2019-12-23 15:50:30 +00:00
BOOST_CHECK ( solidity : : frontend : : test : : searchErrorMessage ( err , ( substring ) ) ) ; \
2017-05-03 08:30:01 +00:00
} while ( 0 )
2020-01-29 17:14:03 +00:00
# define CHECK_ERROR(text, typ, substring) CHECK_ERROR_DIALECT(text, typ, substring, Dialect::yulDeprecated())
2018-12-03 17:06:07 +00:00
2018-06-14 22:29:45 +00:00
BOOST_AUTO_TEST_SUITE ( YulParser )
2017-05-03 08:30:01 +00:00
2018-12-04 10:23:28 +00:00
BOOST_AUTO_TEST_CASE ( builtins_analysis )
{
2018-12-06 23:56:16 +00:00
struct SimpleDialect : public Dialect
2018-12-04 10:23:28 +00:00
{
2018-12-06 23:56:16 +00:00
BuiltinFunction const * builtin ( YulString _name ) const override
2018-12-04 10:23:28 +00:00
{
2018-12-10 03:25:51 +00:00
return _name = = " builtin " _yulstring ? & f : nullptr ;
2018-12-04 10:23:28 +00:00
}
2020-04-06 12:47:44 +00:00
BuiltinFunction f { " builtin " _yulstring , vector < Type > ( 2 ) , vector < Type > ( 3 ) , { } , { } , false , { } } ;
2018-12-04 10:23:28 +00:00
} ;
2019-05-16 08:56:56 +00:00
SimpleDialect dialect ;
2018-12-04 10:23:28 +00:00
BOOST_CHECK ( successParse ( " { let a, b, c := builtin(1, 2) } " , dialect ) ) ;
2021-02-09 13:25:34 +00:00
CHECK_ERROR_DIALECT ( " { let a, b, c := builtin(1) } " , TypeError , " Function \" builtin \" expects 2 arguments but got 1 " , dialect ) ;
CHECK_ERROR_DIALECT ( " { let a, b := builtin(1, 2) } " , DeclarationError , " Variable count mismatch for declaration of \" a, b \" : 2 variables and 3 values. " , dialect ) ;
2018-12-04 10:23:28 +00:00
}
2020-01-16 17:06:27 +00:00
BOOST_AUTO_TEST_CASE ( default_types_set )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
shared_ptr < Block > result = parse (
" { "
" let x:bool := true:bool "
2020-01-29 17:14:20 +00:00
" let z:bool := true "
2020-01-16 17:06:27 +00:00
" let y := add(1, 2) "
" switch y case 0 {} default {} "
" } " ,
EVMDialectTyped : : instance ( EVMVersion { } ) ,
reporter
) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2020-01-16 17:06:27 +00:00
// Use no dialect so that all types are printed.
// This tests that the default types are properly assigned.
BOOST_CHECK_EQUAL ( AsmPrinter { } ( * result ) ,
" { \n "
" let x:bool := true:bool \n "
2020-01-29 17:14:20 +00:00
" let z:bool := true:bool \n "
2020-01-16 17:06:27 +00:00
" let y:u256 := add(1:u256, 2:u256) \n "
" switch y \n "
" case 0:u256 { } \n "
" default { } \n "
" } "
) ;
// Now test again with type dialect. Now the default types
// should be omitted.
BOOST_CHECK_EQUAL ( AsmPrinter { EVMDialectTyped : : instance ( EVMVersion { } ) } ( * result ) ,
" { \n "
2020-01-29 17:14:20 +00:00
" let x:bool := true \n "
" let z:bool := true \n "
2020-01-16 17:06:27 +00:00
" let y := add(1, 2) \n "
" switch y \n "
" case 0 { } \n "
" default { } \n "
" } "
) ;
}
2021-06-29 12:38:59 +00:00
# define CHECK_LOCATION(_actual, _sourceName, _start, _end) \
2021-06-16 10:38:34 +00:00
do { \
2021-06-29 12:38:59 +00:00
BOOST_CHECK_EQUAL ( ( _sourceName ) , ( ( _actual ) . sourceName ? * ( _actual ) . sourceName : " " ) ) ; \
2021-06-16 10:38:34 +00:00
BOOST_CHECK_EQUAL ( ( _start ) , ( _actual ) . start ) ; \
BOOST_CHECK_EQUAL ( ( _end ) , ( _actual ) . end ) ; \
} while ( 0 )
BOOST_AUTO_TEST_CASE ( customSourceLocations_empty_block )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText =
" /// @src 0:234:543 \n "
" {} \n " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( result - > debugData - > location , " source0 " , 234 , 543 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_block_with_children )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText =
" /// @src 0:234:543 \n "
" { \n "
" let x:bool := true:bool \n "
" /// @src 0:123:432 \n "
" let z:bool := true \n "
" let y := add(1, 2) \n "
" } \n " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
BOOST_REQUIRE ( ! ! result ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( result - > debugData - > location , " source0 " , 234 , 543 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 3 , result - > statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( result - > statements . at ( 0 ) ) , " source0 " , 234 , 543 ) ;
CHECK_LOCATION ( locationOf ( result - > statements . at ( 1 ) ) , " source0 " , 123 , 432 ) ;
2021-06-16 10:38:34 +00:00
// [2] is inherited source location
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( result - > statements . at ( 2 ) ) , " source0 " , 123 , 432 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_block_different_sources )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText =
" /// @src 0:234:543 \n "
" { \n "
" let x:bool := true:bool \n "
" /// @src 1:123:432 \n "
" let z:bool := true \n "
" let y := add(1, 2) \n "
" } \n " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( result - > debugData - > location , " source0 " , 234 , 543 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 3 , result - > statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( result - > statements . at ( 0 ) ) , " source0 " , 234 , 543 ) ;
CHECK_LOCATION ( locationOf ( result - > statements . at ( 1 ) ) , " source1 " , 123 , 432 ) ;
2021-06-16 10:38:34 +00:00
// [2] is inherited source location
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( result - > statements . at ( 2 ) ) , " source1 " , 123 , 432 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_block_nested )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText =
" /// @src 0:234:543 \n "
" { \n "
" let y := add(1, 2) \n "
" /// @src 0:343:434 \n "
" switch y case 0 {} default {} \n "
" } \n " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( result - > debugData - > location , " source0 " , 234 , 543 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 2 , result - > statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( result - > statements . at ( 1 ) ) , " source0 " , 343 , 434 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_block_switch_case )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText =
" /// @src 0:234:543 \n "
" { \n "
" let y := add(1, 2) \n "
" /// @src 0:343:434 \n "
" switch y \n "
" /// @src 0:3141:59265 \n "
" case 0 { \n "
" /// @src 0:271:828 \n "
" let z := add(3, 4) \n "
" } \n "
" } \n " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( result - > debugData - > location , " source0 " , 234 , 543 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 2 , result - > statements . size ( ) ) ;
BOOST_REQUIRE ( holds_alternative < Switch > ( result - > statements . at ( 1 ) ) ) ;
auto const & switchStmt = get < Switch > ( result - > statements . at ( 1 ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( switchStmt . debugData - > location , " source0 " , 343 , 434 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 1 , switchStmt . cases . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( switchStmt . cases . at ( 0 ) . debugData - > location , " source0 " , 3141 , 59265 ) ;
2021-06-16 10:38:34 +00:00
auto const & caseBody = switchStmt . cases . at ( 0 ) . body ;
BOOST_REQUIRE_EQUAL ( 1 , caseBody . statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( caseBody . statements . at ( 0 ) ) , " source0 " , 271 , 828 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_inherit_into_outer_scope )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText =
" /// @src 0:1:100 \n "
" { \n "
" { \n "
" /// @src 0:123:432 \n "
" let x:bool := true:bool \n "
" } \n "
" let z:bool := true \n "
" let y := add(1, 2) \n "
" } \n " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2020-01-16 17:06:27 +00:00
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( result - > debugData - > location , " source0 " , 1 , 100 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 3 , result - > statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( result - > statements . at ( 0 ) ) , " source0 " , 1 , 100 ) ;
2021-06-16 10:38:34 +00:00
// First child element must be a block itself with one statement.
BOOST_REQUIRE ( holds_alternative < Block > ( result - > statements . at ( 0 ) ) ) ;
BOOST_REQUIRE_EQUAL ( get < Block > ( result - > statements . at ( 0 ) ) . statements . size ( ) , 1 ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( get < Block > ( result - > statements . at ( 0 ) ) . statements . at ( 0 ) ) , " source0 " , 123 , 432 ) ;
2021-06-16 10:38:34 +00:00
// The next two elements have an inherited source location from the prior inner scope.
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( result - > statements . at ( 1 ) ) , " source0 " , 123 , 432 ) ;
CHECK_LOCATION ( locationOf ( result - > statements . at ( 2 ) ) , " source0 " , 123 , 432 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_assign_empty )
{
// Tests single AST node (e.g. VariableDeclaration) with different source locations for each child.
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText =
" { \n "
" /// @src 0:123:432 \n "
" let a:bool \n "
" /// @src 1:1:10 \n "
" a := true:bool \n "
" } \n " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ; // should still parse
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 2 , result - > statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( result - > statements . at ( 0 ) ) , " source0 " , 123 , 432 ) ;
CHECK_LOCATION ( locationOf ( result - > statements . at ( 1 ) ) , " source1 " , 1 , 10 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_invalid_source_index )
{
// Tests single AST node (e.g. VariableDeclaration) with different source locations for each child.
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText =
" { \n "
" /// @src 1:123:432 \n "
" let a:bool := true:bool \n "
" /// @src 2345:0:8 \n "
" let b:bool := true:bool \n "
" \n "
" } \n " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
BOOST_REQUIRE ( ! ! result ) ; // should still parse
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( errorList . size ( ) = = 1 ) ;
BOOST_TEST ( errorList [ 0 ] - > type ( ) = = Error : : Type : : SyntaxError ) ;
BOOST_TEST ( errorList [ 0 ] - > errorId ( ) = = 2674 _error ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_mixed_locations_1 )
{
// Tests single AST node (e.g. VariableDeclaration) with different source locations for each child.
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText =
" { \n "
" /// @src 0:123:432 \n "
" let x:bool \n "
" /// @src 0:234:2026 \n "
" := true:bool \n "
" } \n " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 1 , result - > statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( result - > statements . at ( 0 ) ) , " source0 " , 123 , 432 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE ( holds_alternative < VariableDeclaration > ( result - > statements . at ( 0 ) ) ) ;
VariableDeclaration const & varDecl = get < VariableDeclaration > ( result - > statements . at ( 0 ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( * varDecl . value ) , " source0 " , 234 , 2026 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_mixed_locations_2 )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src 0:0:5
{
let x : = /// @src 1:2:3
add ( 1 , /// @src 0:4:8
2 )
}
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 1 , result - > statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( result - > debugData - > location , " source0 " , 0 , 5 ) ;
2021-06-16 10:38:34 +00:00
// `let x := add(1, `
BOOST_REQUIRE ( holds_alternative < VariableDeclaration > ( result - > statements . at ( 0 ) ) ) ;
VariableDeclaration const & varDecl = get < VariableDeclaration > ( result - > statements . at ( 0 ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( varDecl . debugData - > location , " source0 " , 0 , 5 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE ( ! ! varDecl . value ) ;
BOOST_REQUIRE ( holds_alternative < FunctionCall > ( * varDecl . value ) ) ;
FunctionCall const & call = get < FunctionCall > ( * varDecl . value ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( call . debugData - > location , " source1 " , 2 , 3 ) ;
2021-06-16 10:38:34 +00:00
// `2`
BOOST_REQUIRE_EQUAL ( 2 , call . arguments . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( locationOf ( call . arguments . at ( 1 ) ) , " source0 " , 4 , 8 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_mixed_locations_3 )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src 1:23:45
{ // Block
{ // Block
sstore ( 0 , 1 ) // FunctionCall
/// @src 0:420:680
}
mstore ( 1 , 2 ) // FunctionCall
}
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 2 , result - > statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( result - > debugData - > location , " source1 " , 23 , 45 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE ( holds_alternative < Block > ( result - > statements . at ( 0 ) ) ) ;
Block const & innerBlock = get < Block > ( result - > statements . at ( 0 ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( innerBlock . debugData - > location , " source1 " , 23 , 45 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 1 , innerBlock . statements . size ( ) ) ;
BOOST_REQUIRE ( holds_alternative < ExpressionStatement > ( result - > statements . at ( 1 ) ) ) ;
ExpressionStatement const & sstoreStmt = get < ExpressionStatement > ( innerBlock . statements . at ( 0 ) ) ;
BOOST_REQUIRE ( holds_alternative < FunctionCall > ( sstoreStmt . expression ) ) ;
FunctionCall const & sstoreCall = get < FunctionCall > ( sstoreStmt . expression ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( sstoreCall . debugData - > location , " source1 " , 23 , 45 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE ( holds_alternative < ExpressionStatement > ( result - > statements . at ( 1 ) ) ) ;
ExpressionStatement mstoreStmt = get < ExpressionStatement > ( result - > statements . at ( 1 ) ) ;
BOOST_REQUIRE ( holds_alternative < FunctionCall > ( mstoreStmt . expression ) ) ;
FunctionCall const & mstoreCall = get < FunctionCall > ( mstoreStmt . expression ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( mstoreCall . debugData - > location , " source0 " , 420 , 680 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_invalid_comments_after_valid )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src 1:23:45
{
/// @src 0:420:680
/// @invalid
let a : bool : = true
}
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE_EQUAL ( 1 , result - > statements . size ( ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( result - > debugData - > location , " source1 " , 23 , 45 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE ( holds_alternative < VariableDeclaration > ( result - > statements . at ( 0 ) ) ) ;
VariableDeclaration const & varDecl = get < VariableDeclaration > ( result - > statements . at ( 0 ) ) ;
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( varDecl . debugData - > location , " source0 " , 420 , 680 ) ;
2021-06-16 10:38:34 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_invalid_suffix )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src 0:420:680foo
{ }
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 14:08:05 +00:00
BOOST_REQUIRE ( ! ! result ) ;
BOOST_REQUIRE ( errorList . size ( ) = = 1 ) ;
BOOST_TEST ( errorList [ 0 ] - > type ( ) = = Error : : Type : : SyntaxError ) ;
BOOST_TEST ( errorList [ 0 ] - > errorId ( ) = = 8387 _error ) ;
2021-06-16 10:38:34 +00:00
CHECK_LOCATION ( result - > debugData - > location , " " , - 1 , - 1 ) ;
}
2021-09-08 16:50:16 +00:00
BOOST_AUTO_TEST_CASE ( customSourceLocations_invalid_prefix )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// abc@src 0:111:222
{ }
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-09-09 16:27:29 +00:00
CHECK_LOCATION ( result - > debugData - > location , " " , - 1 , - 1 ) ;
2021-09-08 16:50:16 +00:00
}
2021-06-16 10:38:34 +00:00
BOOST_AUTO_TEST_CASE ( customSourceLocations_unspecified )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src -1:-1:-1
{ }
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-16 10:38:34 +00:00
CHECK_LOCATION ( result - > debugData - > location , " " , - 1 , - 1 ) ;
}
2021-09-08 16:50:16 +00:00
BOOST_AUTO_TEST_CASE ( customSourceLocations_non_integer )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src a:b:c
{ }
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 14:08:05 +00:00
BOOST_REQUIRE ( ! ! result ) ;
BOOST_REQUIRE ( errorList . size ( ) = = 1 ) ;
BOOST_TEST ( errorList [ 0 ] - > type ( ) = = Error : : Type : : SyntaxError ) ;
BOOST_TEST ( errorList [ 0 ] - > errorId ( ) = = 8387 _error ) ;
2021-09-08 16:50:16 +00:00
CHECK_LOCATION ( result - > debugData - > location , " " , - 1 , - 1 ) ;
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_bad_integer )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src 111111111111111111111:222222222222222222222:333333333333333333333
{ }
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
BOOST_REQUIRE ( ! ! result ) ;
BOOST_REQUIRE ( errorList . size ( ) = = 1 ) ;
BOOST_TEST ( errorList [ 0 ] - > type ( ) = = Error : : Type : : SyntaxError ) ;
BOOST_TEST ( errorList [ 0 ] - > errorId ( ) = = 6367 _error ) ;
CHECK_LOCATION ( result - > debugData - > location , " " , - 1 , - 1 ) ;
}
2021-06-16 10:38:34 +00:00
BOOST_AUTO_TEST_CASE ( customSourceLocations_ensure_last_match )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src 0:123:432
{
/// @src 1:10:20
/// @src 0:30:40
let x : bool : = true
}
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-06-16 10:38:34 +00:00
BOOST_REQUIRE ( holds_alternative < VariableDeclaration > ( result - > statements . at ( 0 ) ) ) ;
VariableDeclaration const & varDecl = get < VariableDeclaration > ( result - > statements . at ( 0 ) ) ;
// Ensure the latest @src per documentation-comment is used (0:30:40).
2021-06-29 12:38:59 +00:00
CHECK_LOCATION ( varDecl . debugData - > location , " source0 " , 30 , 40 ) ;
2021-06-16 10:38:34 +00:00
}
2019-07-09 15:23:14 +00:00
2021-09-08 16:50:16 +00:00
BOOST_AUTO_TEST_CASE ( customSourceLocations_two_locations_no_whitespace )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src 0:111:222@src 1:333:444
{ }
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 14:08:05 +00:00
BOOST_REQUIRE ( ! ! result ) ;
BOOST_REQUIRE ( errorList . size ( ) = = 1 ) ;
BOOST_TEST ( errorList [ 0 ] - > type ( ) = = Error : : Type : : SyntaxError ) ;
BOOST_TEST ( errorList [ 0 ] - > errorId ( ) = = 8387 _error ) ;
CHECK_LOCATION ( result - > debugData - > location , " " , - 1 , - 1 ) ;
2021-09-08 16:50:16 +00:00
}
BOOST_AUTO_TEST_CASE ( customSourceLocations_leading_trailing_whitespace )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = " /// @src 0:111:222 \n {} " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
CHECK_LOCATION ( result - > debugData - > location , " source0 " , 111 , 222 ) ;
}
2021-07-07 11:31:01 +00:00
BOOST_AUTO_TEST_CASE ( customSourceLocations_reference_original_sloc )
{
ErrorList errorList ;
ErrorReporter reporter ( errorList ) ;
auto const sourceText = R " (
/// @src 1:2:3
{
/// @src -1:10:20
let x : bool : = true
}
) " ;
EVMDialectTyped const & dialect = EVMDialectTyped : : instance ( EVMVersion { } ) ;
shared_ptr < Block > result = parse ( sourceText , dialect , reporter ) ;
2021-09-08 16:47:57 +00:00
BOOST_REQUIRE ( ! ! result & & errorList . size ( ) = = 0 ) ;
2021-07-07 11:31:01 +00:00
BOOST_REQUIRE ( holds_alternative < VariableDeclaration > ( result - > statements . at ( 0 ) ) ) ;
VariableDeclaration const & varDecl = get < VariableDeclaration > ( result - > statements . at ( 0 ) ) ;
2021-06-29 12:38:59 +00:00
// -1 points to original source code, which in this case is `"source0"` (which is also
2021-07-12 15:30:50 +00:00
CHECK_LOCATION ( varDecl . debugData - > location , " " , 10 , 20 ) ;
2021-07-07 11:31:01 +00:00
}
2017-05-03 08:30:01 +00:00
BOOST_AUTO_TEST_SUITE_END ( )
} // end namespaces