2014-10-13 13:07:21 +00:00
/*
2016-11-18 23:13:20 +00:00
This file is part of solidity .
2014-10-13 13:07:21 +00:00
2016-11-18 23:13:20 +00:00
solidity is free software : you can redistribute it and / or modify
2014-10-13 13:07:21 +00:00
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 .
2016-11-18 23:13:20 +00:00
solidity is distributed in the hope that it will be useful ,
2014-10-13 13:07:21 +00:00
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
2016-11-18 23:13:20 +00:00
along with solidity . If not , see < http : //www.gnu.org/licenses/>.
2014-10-13 13:07:21 +00:00
*/
/**
* @ author Christian < c @ ethdev . com >
* @ date 2014
* Unit tests for the name and type resolution of the solidity parser .
*/
2017-08-28 18:40:38 +00:00
# include <test/libsolidity/AnalysisFramework.h>
2017-03-03 11:51:51 +00:00
2018-03-14 11:04:04 +00:00
# include <test/Options.h>
2018-02-23 18:29:20 +00:00
2017-08-28 18:40:38 +00:00
# include <libsolidity/ast/AST.h>
2017-03-03 11:51:51 +00:00
2018-10-18 11:35:20 +00:00
# include <libdevcore/Keccak256.h>
2017-03-03 11:51:51 +00:00
2017-08-28 18:40:38 +00:00
# include <boost/test/unit_test.hpp>
2017-03-03 11:51:51 +00:00
# include <string>
2014-10-13 13:07:21 +00:00
2015-01-23 15:37:06 +00:00
using namespace std ;
2018-11-14 16:11:55 +00:00
using namespace langutil ;
2015-01-23 15:37:06 +00:00
2014-10-16 12:08:54 +00:00
namespace dev
{
namespace solidity
{
namespace test
{
2014-10-13 13:07:21 +00:00
2017-08-28 18:40:38 +00:00
BOOST_FIXTURE_TEST_SUITE ( SolidityNameAndTypeResolution , AnalysisFramework )
2014-10-13 13:07:21 +00:00
2015-03-20 16:50:26 +00:00
BOOST_AUTO_TEST_CASE ( function_no_implementation )
{
2017-08-28 18:40:38 +00:00
SourceUnit const * sourceUnit = nullptr ;
2016-12-03 20:52:51 +00:00
char const * text = R " (
2019-09-19 19:31:42 +00:00
abstract contract test {
2019-12-02 20:39:53 +00:00
function functionName ( bytes32 input ) public virtual returns ( bytes32 out ) ;
2016-12-03 20:52:51 +00:00
}
) " ;
2017-08-28 18:40:38 +00:00
sourceUnit = parseAndAnalyse ( text ) ;
2015-08-31 16:44:29 +00:00
std : : vector < ASTPointer < ASTNode > > nodes = sourceUnit - > nodes ( ) ;
2016-08-19 17:57:21 +00:00
ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( nodes [ 1 ] . get ( ) ) ;
BOOST_REQUIRE ( contract ) ;
2017-08-02 10:58:22 +00:00
BOOST_CHECK ( ! contract - > annotation ( ) . unimplementedFunctions . empty ( ) ) ;
2015-09-16 14:56:30 +00:00
BOOST_CHECK ( ! contract - > definedFunctions ( ) [ 0 ] - > isImplemented ( ) ) ;
2015-03-20 16:50:26 +00:00
}
2015-03-27 14:15:34 +00:00
BOOST_AUTO_TEST_CASE ( abstract_contract )
{
2017-08-28 18:40:38 +00:00
SourceUnit const * sourceUnit = nullptr ;
2015-03-27 14:15:34 +00:00
char const * text = R " (
2019-11-05 17:25:34 +00:00
abstract contract base { function foo ( ) public virtual ; }
2019-10-23 20:10:12 +00:00
contract derived is base { function foo ( ) public override { } }
2016-12-03 20:52:51 +00:00
) " ;
2017-08-28 18:40:38 +00:00
sourceUnit = parseAndAnalyse ( text ) ;
2015-08-31 16:44:29 +00:00
std : : vector < ASTPointer < ASTNode > > nodes = sourceUnit - > nodes ( ) ;
2016-08-19 17:57:21 +00:00
ContractDefinition * base = dynamic_cast < ContractDefinition * > ( nodes [ 1 ] . get ( ) ) ;
ContractDefinition * derived = dynamic_cast < ContractDefinition * > ( nodes [ 2 ] . get ( ) ) ;
BOOST_REQUIRE ( base ) ;
2017-08-02 10:58:22 +00:00
BOOST_CHECK ( ! base - > annotation ( ) . unimplementedFunctions . empty ( ) ) ;
2015-09-16 14:56:30 +00:00
BOOST_CHECK ( ! base - > definedFunctions ( ) [ 0 ] - > isImplemented ( ) ) ;
2016-08-19 17:57:21 +00:00
BOOST_REQUIRE ( derived ) ;
2017-08-02 10:58:22 +00:00
BOOST_CHECK ( derived - > annotation ( ) . unimplementedFunctions . empty ( ) ) ;
2015-09-16 14:56:30 +00:00
BOOST_CHECK ( derived - > definedFunctions ( ) [ 0 ] - > isImplemented ( ) ) ;
2015-03-27 14:15:34 +00:00
}
2015-06-23 14:56:59 +00:00
BOOST_AUTO_TEST_CASE ( abstract_contract_with_overload )
{
2017-08-28 18:40:38 +00:00
SourceUnit const * sourceUnit = nullptr ;
2015-06-23 14:56:59 +00:00
char const * text = R " (
2019-12-02 20:39:53 +00:00
abstract contract base { function foo ( bool ) public virtual ; }
2019-09-19 19:31:42 +00:00
abstract contract derived is base { function foo ( uint ) public { } }
2016-12-03 20:52:51 +00:00
) " ;
2017-08-28 18:40:38 +00:00
sourceUnit = parseAndAnalyse ( text ) ;
2015-08-31 16:44:29 +00:00
std : : vector < ASTPointer < ASTNode > > nodes = sourceUnit - > nodes ( ) ;
2016-08-19 17:57:21 +00:00
ContractDefinition * base = dynamic_cast < ContractDefinition * > ( nodes [ 1 ] . get ( ) ) ;
ContractDefinition * derived = dynamic_cast < ContractDefinition * > ( nodes [ 2 ] . get ( ) ) ;
2015-06-23 14:56:59 +00:00
BOOST_REQUIRE ( base ) ;
2017-08-02 10:58:22 +00:00
BOOST_CHECK ( ! base - > annotation ( ) . unimplementedFunctions . empty ( ) ) ;
2015-06-23 14:56:59 +00:00
BOOST_REQUIRE ( derived ) ;
2017-08-02 10:58:22 +00:00
BOOST_CHECK ( ! derived - > annotation ( ) . unimplementedFunctions . empty ( ) ) ;
2015-06-23 14:56:59 +00:00
}
2016-06-06 17:35:55 +00:00
BOOST_AUTO_TEST_CASE ( implement_abstract_via_constructor )
{
2017-08-28 18:40:38 +00:00
SourceUnit const * sourceUnit = nullptr ;
2016-06-06 17:35:55 +00:00
char const * text = R " (
2019-12-02 20:39:53 +00:00
abstract contract base { function foo ( ) public virtual ; }
2019-09-19 19:31:42 +00:00
abstract contract foo is base { constructor ( ) public { } }
2016-06-06 17:35:55 +00:00
) " ;
2017-08-28 18:40:38 +00:00
sourceUnit = parseAndAnalyse ( text ) ;
2016-06-06 17:35:55 +00:00
std : : vector < ASTPointer < ASTNode > > nodes = sourceUnit - > nodes ( ) ;
2016-08-19 17:57:21 +00:00
BOOST_CHECK_EQUAL ( nodes . size ( ) , 3 ) ;
ContractDefinition * derived = dynamic_cast < ContractDefinition * > ( nodes [ 2 ] . get ( ) ) ;
BOOST_REQUIRE ( derived ) ;
2017-08-02 10:58:22 +00:00
BOOST_CHECK ( ! derived - > annotation ( ) . unimplementedFunctions . empty ( ) ) ;
2016-06-06 17:35:55 +00:00
}
2015-01-07 01:07:34 +00:00
BOOST_AUTO_TEST_CASE ( function_canonical_signature )
{
2017-08-28 18:40:38 +00:00
SourceUnit const * sourceUnit = nullptr ;
2016-12-03 20:52:51 +00:00
char const * text = R " (
contract Test {
2017-09-05 15:11:53 +00:00
function foo ( uint256 arg1 , uint64 arg2 , bool arg3 ) public returns ( uint256 ret ) {
2016-12-03 20:52:51 +00:00
ret = arg1 + arg2 ;
}
}
) " ;
2017-08-28 18:40:38 +00:00
sourceUnit = parseAndAnalyse ( text ) ;
2015-08-31 16:44:29 +00:00
for ( ASTPointer < ASTNode > const & node : sourceUnit - > nodes ( ) )
2015-01-07 01:07:34 +00:00
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
2015-08-31 16:44:29 +00:00
auto functions = contract - > definedFunctions ( ) ;
2015-03-24 10:11:27 +00:00
BOOST_CHECK_EQUAL ( " foo(uint256,uint64,bool) " , functions [ 0 ] - > externalSignature ( ) ) ;
2015-01-07 09:45:59 +00:00
}
}
BOOST_AUTO_TEST_CASE ( function_canonical_signature_type_aliases )
{
2017-08-28 18:40:38 +00:00
SourceUnit const * sourceUnit = nullptr ;
2016-12-03 20:52:51 +00:00
char const * text = R " (
contract Test {
2017-09-05 15:11:53 +00:00
function boo ( uint , bytes32 , address ) public returns ( uint ret ) {
2016-12-03 20:52:51 +00:00
ret = 5 ;
}
}
) " ;
2017-08-28 18:40:38 +00:00
sourceUnit = parseAndAnalyse ( text ) ;
2015-08-31 16:44:29 +00:00
for ( ASTPointer < ASTNode > const & node : sourceUnit - > nodes ( ) )
2015-01-07 09:45:59 +00:00
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
2015-08-31 16:44:29 +00:00
auto functions = contract - > definedFunctions ( ) ;
2015-03-25 12:58:15 +00:00
if ( functions . empty ( ) )
continue ;
2015-03-24 10:11:27 +00:00
BOOST_CHECK_EQUAL ( " boo(uint256,bytes32,address) " , functions [ 0 ] - > externalSignature ( ) ) ;
2015-01-07 01:07:34 +00:00
}
}
2015-03-23 17:08:45 +00:00
BOOST_AUTO_TEST_CASE ( function_external_types )
{
2017-08-28 18:40:38 +00:00
SourceUnit const * sourceUnit = nullptr ;
2015-03-23 17:08:45 +00:00
char const * text = R " (
2015-03-25 12:58:15 +00:00
contract C {
uint a ;
}
2015-03-23 17:08:45 +00:00
contract Test {
2018-08-07 13:19:50 +00:00
function boo ( uint , bool , bytes8 , bool [ 2 ] calldata , uint [ ] calldata , C , address [ ] calldata ) external returns ( uint ret ) {
2016-12-03 20:52:51 +00:00
ret = 5 ;
2015-03-23 17:08:45 +00:00
}
2016-12-03 20:52:51 +00:00
}
) " ;
2017-08-28 18:40:38 +00:00
sourceUnit = parseAndAnalyse ( text ) ;
2015-08-31 16:44:29 +00:00
for ( ASTPointer < ASTNode > const & node : sourceUnit - > nodes ( ) )
2015-03-23 17:08:45 +00:00
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
2015-08-31 16:44:29 +00:00
auto functions = contract - > definedFunctions ( ) ;
2015-03-25 12:58:15 +00:00
if ( functions . empty ( ) )
continue ;
2015-03-30 12:34:38 +00:00
BOOST_CHECK_EQUAL ( " boo(uint256,bool,bytes8,bool[2],uint256[],address,address[]) " , functions [ 0 ] - > externalSignature ( ) ) ;
2015-03-23 17:08:45 +00:00
}
}
2015-05-11 11:47:21 +00:00
BOOST_AUTO_TEST_CASE ( enum_external_type )
{
2017-08-28 18:40:38 +00:00
SourceUnit const * sourceUnit = nullptr ;
2015-05-11 11:47:21 +00:00
char const * text = R " (
2018-05-23 09:34:01 +00:00
// test for bug #1801
2015-05-11 11:47:21 +00:00
contract Test {
enum ActionChoices { GoLeft , GoRight , GoStraight , Sit }
function boo ( ActionChoices enumArg ) external returns ( uint ret ) {
2015-05-11 14:24:04 +00:00
ret = 5 ;
2015-05-11 11:47:21 +00:00
}
2016-12-03 20:52:51 +00:00
}
) " ;
2017-08-28 18:40:38 +00:00
sourceUnit = parseAndAnalyse ( text ) ;
2015-08-31 16:44:29 +00:00
for ( ASTPointer < ASTNode > const & node : sourceUnit - > nodes ( ) )
2015-05-11 11:47:21 +00:00
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
2015-08-31 16:44:29 +00:00
auto functions = contract - > definedFunctions ( ) ;
2015-05-11 11:47:21 +00:00
if ( functions . empty ( ) )
continue ;
BOOST_CHECK_EQUAL ( " boo(uint8) " , functions [ 0 ] - > externalSignature ( ) ) ;
}
}
2019-01-17 11:59:11 +00:00
BOOST_AUTO_TEST_CASE ( external_struct_signatures )
2017-06-08 09:14:58 +00:00
{
2017-06-09 16:28:13 +00:00
char const * text = R " (
2017-12-11 02:39:39 +00:00
pragma experimental ABIEncoderV2 ;
2017-06-09 16:28:13 +00:00
contract Test {
enum ActionChoices { GoLeft , GoRight , GoStraight , Sit }
2018-06-06 09:15:22 +00:00
struct Simple { uint i ; }
2017-09-14 15:03:59 +00:00
struct Nested { X [ 2 ] [ ] a ; uint y ; }
2018-06-06 09:15:22 +00:00
struct X { bytes32 x ; Test t ; Simple [ ] s ; }
2018-08-07 13:19:50 +00:00
function f ( ActionChoices , uint , Simple calldata ) external { }
function g ( Test , Nested calldata ) external { }
function h ( function ( Nested memory ) external returns ( uint ) [ ] calldata ) external { }
function i ( Nested [ ] calldata ) external { }
2017-06-09 16:28:13 +00:00
}
) " ;
2019-01-17 11:59:11 +00:00
// Ignore analysis errors. This test only checks that correct signatures
// are generated for external structs, but they are not yet supported
// in code generation and therefore cause an error in the TypeChecker.
SourceUnit const * sourceUnit = parseAnalyseAndReturnError ( text , false , true , true ) . first ;
2017-06-09 16:28:13 +00:00
for ( ASTPointer < ASTNode > const & node : sourceUnit - > nodes ( ) )
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
auto functions = contract - > definedFunctions ( ) ;
BOOST_REQUIRE ( ! functions . empty ( ) ) ;
2018-06-06 09:15:22 +00:00
BOOST_CHECK_EQUAL ( " f(uint8,uint256,(uint256)) " , functions [ 0 ] - > externalSignature ( ) ) ;
BOOST_CHECK_EQUAL ( " g(address,((bytes32,address,(uint256)[])[2][],uint256)) " , functions [ 1 ] - > externalSignature ( ) ) ;
2017-06-09 16:28:13 +00:00
BOOST_CHECK_EQUAL ( " h(function[]) " , functions [ 2 ] - > externalSignature ( ) ) ;
2018-06-06 09:15:22 +00:00
BOOST_CHECK_EQUAL ( " i(((bytes32,address,(uint256)[])[2][],uint256)[]) " , functions [ 3 ] - > externalSignature ( ) ) ;
2017-06-09 16:28:13 +00:00
}
2017-06-08 09:14:58 +00:00
}
2019-01-17 11:59:11 +00:00
BOOST_AUTO_TEST_CASE ( external_struct_signatures_in_libraries )
2017-09-01 11:37:40 +00:00
{
char const * text = R " (
2017-12-11 02:39:39 +00:00
pragma experimental ABIEncoderV2 ;
2017-09-01 11:37:40 +00:00
library Test {
enum ActionChoices { GoLeft , GoRight , GoStraight , Sit }
2018-06-06 09:15:22 +00:00
struct Simple { uint i ; }
2017-09-14 15:03:59 +00:00
struct Nested { X [ 2 ] [ ] a ; uint y ; }
2018-06-06 09:15:22 +00:00
struct X { bytes32 x ; Test t ; Simple [ ] s ; }
2018-08-07 13:19:50 +00:00
function f ( ActionChoices , uint , Simple calldata ) external { }
function g ( Test , Nested calldata ) external { }
function h ( function ( Nested memory ) external returns ( uint ) [ ] calldata ) external { }
function i ( Nested [ ] calldata ) external { }
2017-09-01 11:37:40 +00:00
}
) " ;
2019-01-17 11:59:11 +00:00
// Ignore analysis errors. This test only checks that correct signatures
// are generated for external structs, but calldata structs are not yet supported
// in code generation and therefore cause an error in the TypeChecker.
SourceUnit const * sourceUnit = parseAnalyseAndReturnError ( text , false , true , true ) . first ;
2017-09-01 11:37:40 +00:00
for ( ASTPointer < ASTNode > const & node : sourceUnit - > nodes ( ) )
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
auto functions = contract - > definedFunctions ( ) ;
BOOST_REQUIRE ( ! functions . empty ( ) ) ;
2018-06-06 09:15:22 +00:00
BOOST_CHECK_EQUAL ( " f(Test.ActionChoices,uint256,Test.Simple) " , functions [ 0 ] - > externalSignature ( ) ) ;
2017-09-01 11:37:40 +00:00
BOOST_CHECK_EQUAL ( " g(Test,Test.Nested) " , functions [ 1 ] - > externalSignature ( ) ) ;
BOOST_CHECK_EQUAL ( " h(function[]) " , functions [ 2 ] - > externalSignature ( ) ) ;
BOOST_CHECK_EQUAL ( " i(Test.Nested[]) " , functions [ 3 ] - > externalSignature ( ) ) ;
}
}
2017-09-14 15:03:59 +00:00
BOOST_AUTO_TEST_CASE ( struct_with_mapping_in_library )
{
char const * text = R " (
library Test {
struct Nested { mapping ( uint = > uint ) [ 2 ] [ ] a ; uint y ; }
struct X { Nested n ; }
function f ( X storage x ) external { }
}
) " ;
SourceUnit const * sourceUnit = parseAndAnalyse ( text ) ;
for ( ASTPointer < ASTNode > const & node : sourceUnit - > nodes ( ) )
if ( ContractDefinition * contract = dynamic_cast < ContractDefinition * > ( node . get ( ) ) )
{
auto functions = contract - > definedFunctions ( ) ;
BOOST_REQUIRE ( ! functions . empty ( ) ) ;
BOOST_CHECK_EQUAL ( " f(Test.X storage) " , functions [ 0 ] - > externalSignature ( ) ) ;
}
}
2018-05-30 19:04:34 +00:00
BOOST_AUTO_TEST_CASE ( state_variable_accessors )
2017-09-14 15:03:59 +00:00
{
char const * text = R " (
2018-05-30 19:04:34 +00:00
contract test {
function fun ( ) public {
uint64 ( 2 ) ;
}
uint256 public foo ;
mapping ( uint = > bytes4 ) public map ;
mapping ( uint = > mapping ( uint = > bytes4 ) ) public multiple_map ;
2017-09-14 15:03:59 +00:00
}
) " ;
2018-05-30 19:04:34 +00:00
SourceUnit const * source ;
ContractDefinition const * contract ;
source = parseAndAnalyse ( text ) ;
BOOST_REQUIRE ( ( contract = retrieveContractByName ( * source , " test " ) ) ! = nullptr ) ;
FunctionTypePointer function = retrieveFunctionBySignature ( * contract , " foo() " ) ;
BOOST_REQUIRE ( function & & function - > hasDeclaration ( ) ) ;
auto returnParams = function - > returnParameterTypes ( ) ;
BOOST_CHECK_EQUAL ( returnParams . at ( 0 ) - > canonicalName ( ) , " uint256 " ) ;
BOOST_CHECK ( function - > stateMutability ( ) = = StateMutability : : View ) ;
2017-09-14 15:03:59 +00:00
2018-05-30 19:04:34 +00:00
function = retrieveFunctionBySignature ( * contract , " map(uint256) " ) ;
BOOST_REQUIRE ( function & & function - > hasDeclaration ( ) ) ;
auto params = function - > parameterTypes ( ) ;
BOOST_CHECK_EQUAL ( params . at ( 0 ) - > canonicalName ( ) , " uint256 " ) ;
returnParams = function - > returnParameterTypes ( ) ;
BOOST_CHECK_EQUAL ( returnParams . at ( 0 ) - > canonicalName ( ) , " bytes4 " ) ;
BOOST_CHECK ( function - > stateMutability ( ) = = StateMutability : : View ) ;
function = retrieveFunctionBySignature ( * contract , " multiple_map(uint256,uint256) " ) ;
BOOST_REQUIRE ( function & & function - > hasDeclaration ( ) ) ;
params = function - > parameterTypes ( ) ;
BOOST_CHECK_EQUAL ( params . at ( 0 ) - > canonicalName ( ) , " uint256 " ) ;
BOOST_CHECK_EQUAL ( params . at ( 1 ) - > canonicalName ( ) , " uint256 " ) ;
returnParams = function - > returnParameterTypes ( ) ;
BOOST_CHECK_EQUAL ( returnParams . at ( 0 ) - > canonicalName ( ) , " bytes4 " ) ;
BOOST_CHECK ( function - > stateMutability ( ) = = StateMutability : : View ) ;
2017-09-14 15:03:59 +00:00
}
2018-05-30 19:04:34 +00:00
BOOST_AUTO_TEST_CASE ( private_state_variable )
2017-09-14 15:03:59 +00:00
{
char const * text = R " (
2018-05-30 19:04:34 +00:00
contract test {
function fun ( ) public {
uint64 ( 2 ) ;
2017-09-27 13:11:44 +00:00
}
2018-05-30 19:04:34 +00:00
uint256 private foo ;
uint256 internal bar ;
2017-09-27 13:11:44 +00:00
}
) " ;
2018-05-30 19:04:34 +00:00
ContractDefinition const * contract ;
SourceUnit const * source = parseAndAnalyse ( text ) ;
BOOST_CHECK ( ( contract = retrieveContractByName ( * source , " test " ) ) ! = nullptr ) ;
FunctionTypePointer function ;
function = retrieveFunctionBySignature ( * contract , " foo() " ) ;
BOOST_CHECK_MESSAGE ( function = = nullptr , " Accessor function of a private variable should not exist " ) ;
function = retrieveFunctionBySignature ( * contract , " bar() " ) ;
BOOST_CHECK_MESSAGE ( function = = nullptr , " Accessor function of an internal variable should not exist " ) ;
2017-09-20 13:54:41 +00:00
}
2018-05-30 19:04:34 +00:00
BOOST_AUTO_TEST_CASE ( string )
2018-02-16 15:55:21 +00:00
{
2018-05-30 19:04:34 +00:00
char const * sourceCode = R " (
2018-02-16 15:55:21 +00:00
contract C {
2018-05-30 19:04:34 +00:00
string s ;
2018-08-07 13:19:50 +00:00
function f ( string calldata x ) external { s = x ; }
2018-02-16 15:55:21 +00:00
}
) " ;
2018-05-30 19:04:34 +00:00
BOOST_CHECK_NO_THROW ( parseAndAnalyse ( sourceCode ) ) ;
2018-05-23 09:36:39 +00:00
}
2018-05-30 19:04:34 +00:00
BOOST_AUTO_TEST_CASE ( dynamic_return_types_not_possible )
2018-05-23 09:36:39 +00:00
{
2018-05-30 19:04:34 +00:00
char const * sourceCode = R " (
2019-09-19 19:31:42 +00:00
abstract contract C {
2019-12-02 20:39:53 +00:00
function f ( uint ) public virtual returns ( string memory ) ;
2018-05-30 19:04:34 +00:00
function g ( ) public {
2018-06-28 13:19:53 +00:00
string memory x = this . f ( 2 ) ;
2018-05-30 19:04:34 +00:00
// we can assign to x but it is not usable.
bytes ( x ) . length ;
2018-02-16 15:55:21 +00:00
}
}
) " ;
2018-05-30 19:04:34 +00:00
if ( dev : : test : : Options : : get ( ) . evmVersion ( ) = = EVMVersion : : homestead ( ) )
2018-06-28 13:19:53 +00:00
CHECK_ERROR ( sourceCode , TypeError , " Type inaccessible dynamic type is not implicitly convertible to expected type string memory. " ) ;
2018-05-30 19:04:34 +00:00
else
2018-06-28 13:19:53 +00:00
CHECK_SUCCESS_NO_WARNINGS ( sourceCode ) ;
2018-05-23 09:36:39 +00:00
}
2018-05-30 19:04:34 +00:00
BOOST_AUTO_TEST_CASE ( warn_nonpresent_pragma )
2018-05-23 09:36:39 +00:00
{
char const * text = R " (
2018-05-30 19:04:34 +00:00
contract C { }
2018-02-16 15:55:21 +00:00
) " ;
2018-05-30 19:04:34 +00:00
auto sourceAndError = parseAnalyseAndReturnError ( text , true , false ) ;
BOOST_REQUIRE ( ! sourceAndError . second . empty ( ) ) ;
BOOST_REQUIRE ( ! ! sourceAndError . first ) ;
BOOST_CHECK ( searchErrorMessage ( * sourceAndError . second . front ( ) , " Source file does not specify required compiler version! " ) ) ;
2018-02-16 15:55:21 +00:00
}
2018-05-30 19:04:34 +00:00
BOOST_AUTO_TEST_CASE ( returndatasize_as_variable )
2018-05-23 09:36:39 +00:00
{
char const * text = R " (
2018-07-09 13:04:27 +00:00
contract C { function f ( ) public pure { uint returndatasize ; returndatasize ; assembly { pop ( returndatasize ( ) ) } } }
2018-02-16 16:32:54 +00:00
) " ;
2018-05-30 19:04:34 +00:00
vector < pair < Error : : Type , std : : string > > expectations ( vector < pair < Error : : Type , std : : string > > {
2018-07-09 13:04:27 +00:00
{ Error : : Type : : Warning , " Variable is shadowed in inline assembly by an instruction of the same name " }
2018-05-30 19:04:34 +00:00
} ) ;
if ( ! dev : : test : : Options : : get ( ) . evmVersion ( ) . supportsReturndata ( ) )
2019-02-26 18:21:32 +00:00
expectations . emplace_back ( make_pair ( Error : : Type : : TypeError , std : : string ( " \" returndatasize \" instruction is only available for Byzantium-compatible VMs " ) ) ) ;
2018-05-30 19:04:34 +00:00
CHECK_ALLOW_MULTI ( text , expectations ) ;
2018-02-16 16:32:54 +00:00
}
2018-06-04 17:14:25 +00:00
BOOST_AUTO_TEST_CASE ( create2_as_variable )
{
char const * text = R " (
2018-07-09 13:04:27 +00:00
contract c { function f ( ) public { uint create2 ; create2 ; assembly { pop ( create2 ( 0 , 0 , 0 , 0 ) ) } } }
2018-06-04 17:14:25 +00:00
) " ;
// This needs special treatment, because the message mentions the EVM version,
// so cannot be run via isoltest.
2018-09-18 22:42:33 +00:00
vector < pair < Error : : Type , std : : string > > expectations ( vector < pair < Error : : Type , std : : string > > {
{ Error : : Type : : Warning , " Variable is shadowed in inline assembly by an instruction of the same name " }
} ) ;
if ( ! dev : : test : : Options : : get ( ) . evmVersion ( ) . hasCreate2 ( ) )
2019-02-26 18:21:32 +00:00
expectations . emplace_back ( make_pair ( Error : : Type : : TypeError , std : : string ( " \" create2 \" instruction is only available for Constantinople-compatible VMs " ) ) ) ;
2018-09-18 22:42:33 +00:00
CHECK_ALLOW_MULTI ( text , expectations ) ;
2018-06-04 17:14:25 +00:00
}
2018-09-25 21:37:46 +00:00
BOOST_AUTO_TEST_CASE ( extcodehash_as_variable )
{
char const * text = R " (
contract c { function f ( ) public view { uint extcodehash ; extcodehash ; assembly { pop ( extcodehash ( 0 ) ) } } }
) " ;
// This needs special treatment, because the message mentions the EVM version,
// so cannot be run via isoltest.
2019-02-25 14:59:09 +00:00
vector < pair < Error : : Type , std : : string > > expectations ( vector < pair < Error : : Type , std : : string > > {
{ Error : : Type : : Warning , " Variable is shadowed in inline assembly by an instruction of the same name " }
} ) ;
if ( ! dev : : test : : Options : : get ( ) . evmVersion ( ) . hasExtCodeHash ( ) )
2019-02-26 18:21:32 +00:00
expectations . emplace_back ( make_pair ( Error : : Type : : TypeError , std : : string ( " \" extcodehash \" instruction is only available for Constantinople-compatible VMs " ) ) ) ;
2019-02-25 14:59:09 +00:00
CHECK_ALLOW_MULTI ( text , expectations ) ;
2018-09-25 21:37:46 +00:00
}
2018-02-26 10:13:21 +00:00
BOOST_AUTO_TEST_CASE ( getter_is_memory_type )
{
char const * text = R " (
contract C {
struct S { string m ; }
string [ ] public x ;
S [ ] public y ;
}
) " ;
CHECK_SUCCESS_NO_WARNINGS ( text ) ;
// Check that the getters return a memory strings, not a storage strings.
2019-04-15 13:27:51 +00:00
ContractDefinition const & c = dynamic_cast < ContractDefinition const & > ( * compiler ( ) . ast ( " " ) . nodes ( ) . at ( 1 ) ) ;
2018-02-26 10:13:21 +00:00
BOOST_CHECK ( c . interfaceFunctions ( ) . size ( ) = = 2 ) ;
for ( auto const & f : c . interfaceFunctions ( ) )
{
auto const & retType = f . second - > returnParameterTypes ( ) . at ( 0 ) ;
BOOST_CHECK ( retType - > dataStoredIn ( DataLocation : : Memory ) ) ;
}
}
2018-08-15 12:40:20 +00:00
BOOST_AUTO_TEST_CASE ( address_staticcall )
{
char const * sourceCode = R " (
contract C {
function f ( ) public view returns ( bool ) {
2018-08-15 21:30:09 +00:00
( bool success , ) = address ( 0x4242 ) . staticcall ( " " ) ;
return success ;
2018-08-15 12:40:20 +00:00
}
}
) " ;
if ( dev : : test : : Options : : get ( ) . evmVersion ( ) . hasStaticCall ( ) )
CHECK_SUCCESS_NO_WARNINGS ( sourceCode ) ;
else
CHECK_ERROR ( sourceCode , TypeError , " \" staticcall \" is not supported by the VM version. " ) ;
}
2018-08-15 13:52:24 +00:00
BOOST_AUTO_TEST_CASE ( address_staticcall_value )
{
if ( dev : : test : : Options : : get ( ) . evmVersion ( ) . hasStaticCall ( ) )
{
char const * sourceCode = R " (
contract C {
function f ( ) public view {
address ( 0x4242 ) . staticcall . value ;
}
}
) " ;
2019-02-12 15:09:16 +00:00
CHECK_ERROR ( sourceCode , TypeError , " Member \" value \" is only available for payable functions. " ) ;
2018-08-15 13:52:24 +00:00
}
}
2018-08-15 21:30:09 +00:00
BOOST_AUTO_TEST_CASE ( address_call_full_return_type )
{
char const * sourceCode = R " (
contract C {
function f ( ) public {
( bool success , bytes memory m ) = address ( 0x4242 ) . call ( " " ) ;
success ; m ;
}
}
) " ;
if ( dev : : test : : Options : : get ( ) . evmVersion ( ) . supportsReturndata ( ) )
CHECK_SUCCESS_NO_WARNINGS ( sourceCode ) ;
else
CHECK_ERROR ( sourceCode , TypeError , " Type inaccessible dynamic type is not implicitly convertible to expected type bytes memory. " ) ;
}
BOOST_AUTO_TEST_CASE ( address_delegatecall_full_return_type )
{
char const * sourceCode = R " (
contract C {
function f ( ) public {
( bool success , bytes memory m ) = address ( 0x4242 ) . delegatecall ( " " ) ;
success ; m ;
}
}
) " ;
if ( dev : : test : : Options : : get ( ) . evmVersion ( ) . supportsReturndata ( ) )
CHECK_SUCCESS_NO_WARNINGS ( sourceCode ) ;
else
CHECK_ERROR ( sourceCode , TypeError , " Type inaccessible dynamic type is not implicitly convertible to expected type bytes memory. " ) ;
}
BOOST_AUTO_TEST_CASE ( address_staticcall_full_return_type )
{
if ( dev : : test : : Options : : get ( ) . evmVersion ( ) . hasStaticCall ( ) )
{
char const * sourceCode = R " (
contract C {
function f ( ) public view {
( bool success , bytes memory m ) = address ( 0x4242 ) . staticcall ( " " ) ;
success ; m ;
}
}
) " ;
CHECK_SUCCESS_NO_WARNINGS ( sourceCode ) ;
}
}
2014-10-13 13:07:21 +00:00
BOOST_AUTO_TEST_SUITE_END ( )
2014-10-16 12:08:54 +00:00
}
}
} // end namespaces