2015-09-16 14:56:30 +00:00
/*
2016-11-18 23:13:20 +00:00
This file is part of solidity .
2015-09-16 14:56:30 +00:00
2016-11-18 23:13:20 +00:00
solidity is free software : you can redistribute it and / or modify
2015-09-16 14:56:30 +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 ,
2015-09-16 14:56:30 +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/>.
2015-09-16 14:56:30 +00:00
*/
2020-07-17 14:54:12 +00:00
// SPDX-License-Identifier: GPL-3.0
2015-09-16 14:56:30 +00:00
/**
* @ author Christian < c @ ethdev . com >
* @ date 2015
* Type analyzer and checker .
*/
2015-10-20 22:21:52 +00:00
# include <libsolidity/analysis/TypeChecker.h>
# include <libsolidity/ast/AST.h>
2019-12-03 00:02:33 +00:00
# include <libsolidity/ast/ASTUtils.h>
2019-04-15 13:33:39 +00:00
# include <libsolidity/ast/TypeProvider.h>
2018-11-28 11:17:30 +00:00
2018-11-23 10:18:57 +00:00
# include <libyul/AsmAnalysis.h>
# include <libyul/AsmAnalysisInfo.h>
# include <libyul/AsmData.h>
2018-12-06 23:56:16 +00:00
2018-11-14 13:59:30 +00:00
# include <liblangutil/ErrorReporter.h>
2018-11-28 11:17:30 +00:00
2020-01-06 10:52:23 +00:00
# include <libsolutil/Algorithms.h>
# include <libsolutil/StringUtils.h>
2018-11-28 11:17:30 +00:00
# include <boost/algorithm/string/join.hpp>
2018-12-17 11:30:08 +00:00
# include <boost/algorithm/string/predicate.hpp>
2020-07-06 19:40:50 +00:00
# include <boost/range/adaptor/reversed.hpp>
2018-11-28 11:17:30 +00:00
# include <memory>
# include <vector>
2015-09-16 14:56:30 +00:00
using namespace std ;
2019-12-11 16:31:36 +00:00
using namespace solidity ;
using namespace solidity : : util ;
using namespace solidity : : langutil ;
using namespace solidity : : frontend ;
2015-09-16 14:56:30 +00:00
2019-03-04 13:33:46 +00:00
bool TypeChecker : : typeSupportedByOldABIEncoder ( Type const & _type , bool _isLibraryCall )
2018-02-19 17:21:02 +00:00
{
2019-02-04 17:13:41 +00:00
if ( _isLibraryCall & & _type . dataStoredIn ( DataLocation : : Storage ) )
2018-02-19 17:21:02 +00:00
return true ;
2018-06-14 18:19:36 +00:00
if ( _type . category ( ) = = Type : : Category : : Struct )
2018-02-19 17:21:02 +00:00
return false ;
2018-06-14 18:19:36 +00:00
if ( _type . category ( ) = = Type : : Category : : Array )
2018-02-19 17:21:02 +00:00
{
auto const & arrayType = dynamic_cast < ArrayType const & > ( _type ) ;
auto base = arrayType . baseType ( ) ;
2019-02-04 17:13:41 +00:00
if ( ! typeSupportedByOldABIEncoder ( * base , _isLibraryCall ) | | ( base - > category ( ) = = Type : : Category : : Array & & base - > isDynamicallySized ( ) ) )
2018-02-19 17:21:02 +00:00
return false ;
}
return true ;
}
2020-06-11 15:17:07 +00:00
bool TypeChecker : : checkTypeRequirements ( SourceUnit const & _source )
2015-09-16 14:56:30 +00:00
{
2020-06-11 22:16:24 +00:00
m_currentSourceUnit = & _source ;
2020-06-11 15:17:07 +00:00
_source . accept ( * this ) ;
2020-06-11 22:16:24 +00:00
m_currentSourceUnit = nullptr ;
2017-05-11 13:26:35 +00:00
return Error : : containsOnlyWarnings ( m_errorReporter . errors ( ) ) ;
2015-09-16 14:56:30 +00:00
}
TypePointer const & TypeChecker : : type ( Expression const & _expression ) const
{
solAssert ( ! ! _expression . annotation ( ) . type , " Type requested but not present. " ) ;
return _expression . annotation ( ) . type ;
}
TypePointer const & TypeChecker : : type ( VariableDeclaration const & _variable ) const
{
solAssert ( ! ! _variable . annotation ( ) . type , " Type requested but not present. " ) ;
return _variable . annotation ( ) . type ;
}
bool TypeChecker : : visit ( ContractDefinition const & _contract )
{
2020-06-09 16:17:58 +00:00
m_currentContract = & _contract ;
2015-11-19 17:02:04 +00:00
2015-09-16 14:56:30 +00:00
ASTNode : : listAccept ( _contract . baseContracts ( ) , * this ) ;
2017-03-21 14:05:59 +00:00
for ( auto const & n : _contract . subNodes ( ) )
2018-11-29 17:18:17 +00:00
n - > accept ( * this ) ;
2015-09-16 14:56:30 +00:00
2020-07-14 08:32:11 +00:00
m_currentContract = nullptr ;
2020-07-06 19:40:50 +00:00
2015-09-16 14:56:30 +00:00
return false ;
}
2017-06-21 17:32:56 +00:00
void TypeChecker : : checkDoubleStorageAssignment ( Assignment const & _assignment )
{
TupleType const & lhs = dynamic_cast < TupleType const & > ( * type ( _assignment . leftHandSide ( ) ) ) ;
TupleType const & rhs = dynamic_cast < TupleType const & > ( * type ( _assignment . rightHandSide ( ) ) ) ;
2018-08-07 16:44:51 +00:00
if ( lhs . components ( ) . size ( ) ! = rhs . components ( ) . size ( ) )
{
solAssert ( m_errorReporter . hasErrors ( ) , " " ) ;
return ;
}
2017-06-21 17:32:56 +00:00
size_t storageToStorageCopies = 0 ;
size_t toStorageCopies = 0 ;
for ( size_t i = 0 ; i < lhs . components ( ) . size ( ) ; + + i )
{
2019-04-15 13:33:39 +00:00
ReferenceType const * ref = dynamic_cast < ReferenceType const * > ( lhs . components ( ) [ i ] ) ;
2017-06-21 17:32:56 +00:00
if ( ! ref | | ! ref - > dataStoredIn ( DataLocation : : Storage ) | | ref - > isPointer ( ) )
continue ;
toStorageCopies + + ;
2018-08-07 16:44:51 +00:00
if ( rhs . components ( ) [ i ] - > dataStoredIn ( DataLocation : : Storage ) )
2017-06-21 17:32:56 +00:00
storageToStorageCopies + + ;
}
if ( storageToStorageCopies > = 1 & & toStorageCopies > = 2 )
m_errorReporter . warning (
2020-05-05 22:38:28 +00:00
7238 _error ,
2017-06-21 17:32:56 +00:00
_assignment . location ( ) ,
" This assignment performs two copies to storage. Since storage copies do not first "
" copy to a temporary location, one of them might be overwritten before the second "
" is executed and thus may have unexpected effects. It is safer to perform the copies "
" separately or assign to storage pointers first. "
) ;
}
2018-09-04 14:24:21 +00:00
TypePointers TypeChecker : : typeCheckABIDecodeAndRetrieveReturnType ( FunctionCall const & _functionCall , bool _abiEncoderV2 )
2018-06-30 16:09:13 +00:00
{
vector < ASTPointer < Expression const > > arguments = _functionCall . arguments ( ) ;
if ( arguments . size ( ) ! = 2 )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
5782 _error ,
2018-06-30 16:09:13 +00:00
_functionCall . location ( ) ,
" This function takes two arguments, but " +
toString ( arguments . size ( ) ) +
" were provided. "
) ;
2019-03-04 17:59:03 +00:00
if ( arguments . size ( ) > = 1 )
2019-09-03 16:30:00 +00:00
if (
! type ( * arguments . front ( ) ) - > isImplicitlyConvertibleTo ( * TypeProvider : : bytesMemory ( ) ) & &
! type ( * arguments . front ( ) ) - > isImplicitlyConvertibleTo ( * TypeProvider : : bytesCalldata ( ) )
)
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
1956 _error ,
2019-03-04 17:59:03 +00:00
arguments . front ( ) - > location ( ) ,
2019-09-03 16:30:00 +00:00
" The first argument to \" abi.decode \" must be implicitly convertible to "
" bytes memory or bytes calldata, but is of type " +
2019-03-04 17:59:03 +00:00
type ( * arguments . front ( ) ) - > toString ( ) +
2019-09-03 16:30:00 +00:00
" . "
2019-03-04 17:59:03 +00:00
) ;
2018-06-30 16:09:13 +00:00
if ( arguments . size ( ) < 2 )
2018-09-04 14:24:21 +00:00
return { } ;
2018-06-30 16:09:13 +00:00
// The following is a rather syntactic restriction, but we check it here anyway:
// The second argument has to be a tuple expression containing type names.
TupleExpression const * tupleExpression = dynamic_cast < TupleExpression const * > ( arguments [ 1 ] . get ( ) ) ;
if ( ! tupleExpression )
{
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
6444 _error ,
2018-06-30 16:09:13 +00:00
arguments [ 1 ] - > location ( ) ,
" The second argument to \" abi.decode \" has to be a tuple of types. "
) ;
2018-09-04 14:24:21 +00:00
return { } ;
2018-06-30 16:09:13 +00:00
}
2018-09-04 14:24:21 +00:00
TypePointers components ;
2018-06-30 16:09:13 +00:00
for ( auto const & typeArgument : tupleExpression - > components ( ) )
{
solAssert ( typeArgument , " " ) ;
2019-04-15 13:33:39 +00:00
if ( TypeType const * argTypeType = dynamic_cast < TypeType const * > ( type ( * typeArgument ) ) )
2018-06-30 16:09:13 +00:00
{
TypePointer actualType = argTypeType - > actualType ( ) ;
solAssert ( actualType , " " ) ;
// We force memory because the parser currently cannot handle
// data locations. Furthermore, storage can be a little dangerous and
// calldata is not really implemented anyway.
2019-04-15 13:33:39 +00:00
actualType = TypeProvider : : withLocationIfReference ( DataLocation : : Memory , actualType ) ;
2018-09-05 15:59:55 +00:00
// We force address payable for address types.
if ( actualType - > category ( ) = = Type : : Category : : Address )
2019-04-17 11:40:50 +00:00
actualType = TypeProvider : : payableAddress ( ) ;
2018-06-30 16:09:13 +00:00
solAssert (
! actualType - > dataStoredIn ( DataLocation : : CallData ) & &
! actualType - > dataStoredIn ( DataLocation : : Storage ) ,
" "
) ;
if ( ! actualType - > fullEncodingType ( false , _abiEncoderV2 , false ) )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
9611 _error ,
2018-06-30 16:09:13 +00:00
typeArgument - > location ( ) ,
2018-10-18 21:53:59 +00:00
" Decoding type " + actualType - > toString ( false ) + " not supported. "
2018-06-30 16:09:13 +00:00
) ;
2020-05-26 17:04:59 +00:00
if ( auto referenceType = dynamic_cast < ReferenceType const * > ( actualType ) )
{
auto result = referenceType - > validForLocation ( referenceType - > location ( ) ) ;
if ( ! result )
m_errorReporter . typeError (
6118 _error ,
typeArgument - > location ( ) ,
result . message ( )
) ;
}
2018-06-30 16:09:13 +00:00
components . push_back ( actualType ) ;
}
else
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 1039 _error , typeArgument - > location ( ) , " Argument has to be a type name. " ) ;
2019-04-17 11:40:50 +00:00
components . push_back ( TypeProvider : : emptyTuple ( ) ) ;
2018-06-30 16:09:13 +00:00
}
}
2018-09-04 14:24:21 +00:00
return components ;
2018-06-30 16:09:13 +00:00
}
2019-01-10 15:28:39 +00:00
TypePointers TypeChecker : : typeCheckMetaTypeFunctionAndRetrieveReturnType ( FunctionCall const & _functionCall )
{
vector < ASTPointer < Expression const > > arguments = _functionCall . arguments ( ) ;
if ( arguments . size ( ) ! = 1 )
{
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
8885 _error ,
2019-01-10 15:28:39 +00:00
_functionCall . location ( ) ,
" This function takes one argument, but " +
toString ( arguments . size ( ) ) +
" were provided. "
) ;
return { } ;
}
TypePointer firstArgType = type ( * arguments . front ( ) ) ;
2020-05-07 16:24:37 +00:00
bool wrongType = false ;
if ( firstArgType - > category ( ) = = Type : : Category : : TypeType )
{
TypeType const * typeTypePtr = dynamic_cast < TypeType const * > ( firstArgType ) ;
Type : : Category typeCategory = typeTypePtr - > actualType ( ) - > category ( ) ;
if (
typeCategory ! = Type : : Category : : Contract & &
typeCategory ! = Type : : Category : : Integer
)
wrongType = true ;
}
else
wrongType = true ;
if ( wrongType )
2019-01-10 15:28:39 +00:00
{
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
4259 _error ,
2019-01-10 15:28:39 +00:00
arguments . front ( ) - > location ( ) ,
2020-05-07 16:24:37 +00:00
" Invalid type for argument in the function call. "
" A contract type or an integer type is required, but " +
type ( * arguments . front ( ) ) - > toString ( true ) + " provided. "
2019-01-10 15:28:39 +00:00
) ;
return { } ;
}
2019-04-17 11:40:50 +00:00
return { TypeProvider : : meta ( dynamic_cast < TypeType const & > ( * firstArgType ) . actualType ( ) ) } ;
2019-01-10 15:28:39 +00:00
}
2015-09-16 14:56:30 +00:00
void TypeChecker : : endVisit ( InheritanceSpecifier const & _inheritance )
{
auto base = dynamic_cast < ContractDefinition const * > ( & dereference ( _inheritance . name ( ) ) ) ;
solAssert ( base , " Base contract not available. " ) ;
2020-05-04 16:38:00 +00:00
solAssert ( m_currentContract , " " ) ;
2015-09-16 14:56:30 +00:00
2020-06-09 16:17:58 +00:00
if ( m_currentContract - > isInterface ( ) & & ! base - > isInterface ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6536 _error , _inheritance . location ( ) , " Interfaces can only inherit from other interfaces. " ) ;
2020-01-02 21:32:35 +00:00
2015-09-16 14:56:30 +00:00
auto const & arguments = _inheritance . arguments ( ) ;
2017-08-21 14:43:15 +00:00
TypePointers parameterTypes ;
2019-01-17 11:59:11 +00:00
if ( ! base - > isInterface ( ) )
2017-08-21 14:43:15 +00:00
// Interfaces do not have constructors, so there are zero parameters.
parameterTypes = ContractType ( * base ) . newExpressionType ( ) - > parameterTypes ( ) ;
2018-04-04 18:53:23 +00:00
if ( arguments )
2015-12-09 16:37:19 +00:00
{
2018-04-04 18:53:23 +00:00
if ( parameterTypes . size ( ) ! = arguments - > size ( ) )
{
2018-07-06 20:53:55 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
7927 _error ,
2018-07-06 20:53:55 +00:00
_inheritance . location ( ) ,
" Wrong argument count for constructor call: " +
toString ( arguments - > size ( ) ) +
" arguments given but expected " +
toString ( parameterTypes . size ( ) ) +
2018-07-10 23:44:51 +00:00
" . Remove parentheses if you do not want to provide arguments here. "
2018-07-06 20:53:55 +00:00
) ;
2018-04-04 18:53:23 +00:00
}
2018-07-10 10:05:41 +00:00
for ( size_t i = 0 ; i < std : : min ( arguments - > size ( ) , parameterTypes . size ( ) ) ; + + i )
2019-03-04 17:59:03 +00:00
{
BoolResult result = type ( * ( * arguments ) [ i ] ) - > isImplicitlyConvertibleTo ( * parameterTypes [ i ] ) ;
if ( ! result )
m_errorReporter . typeErrorConcatenateDescriptions (
2020-05-05 22:38:28 +00:00
9827 _error ,
2018-04-04 18:53:23 +00:00
( * arguments ) [ i ] - > location ( ) ,
" Invalid type for argument in constructor call. "
" Invalid implicit conversion from " +
type ( * ( * arguments ) [ i ] ) - > toString ( ) +
" to " +
parameterTypes [ i ] - > toString ( ) +
2019-03-04 17:59:03 +00:00
" requested. " ,
result . message ( )
2018-04-04 18:53:23 +00:00
) ;
2019-03-04 17:59:03 +00:00
}
2018-04-04 18:53:23 +00:00
}
2015-11-22 19:39:10 +00:00
}
2020-04-15 10:42:15 +00:00
void TypeChecker : : endVisit ( ModifierDefinition const & _modifier )
{
2020-09-07 08:45:04 +00:00
if ( _modifier . virtualSemantics ( ) )
if ( auto const * contractDef = dynamic_cast < ContractDefinition const * > ( _modifier . scope ( ) ) )
if ( contractDef - > isLibrary ( ) )
m_errorReporter . typeError (
3275 _error ,
_modifier . location ( ) ,
" Modifiers in a library cannot be virtual. "
) ;
2020-04-15 10:42:15 +00:00
if ( ! _modifier . isImplemented ( ) & & ! _modifier . virtualSemantics ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 8063 _error , _modifier . location ( ) , " Modifiers without implementation must be marked virtual. " ) ;
2020-04-15 10:42:15 +00:00
}
2015-09-16 14:56:30 +00:00
bool TypeChecker : : visit ( FunctionDefinition const & _function )
{
2019-11-27 13:02:52 +00:00
if ( _function . markedVirtual ( ) )
{
2020-05-04 16:38:00 +00:00
if ( _function . isFree ( ) )
m_errorReporter . syntaxError ( 4493 _error , _function . location ( ) , " Free functions cannot be virtual. " ) ;
else if ( _function . isConstructor ( ) )
2020-06-10 16:19:42 +00:00
m_errorReporter . typeError ( 7001 _error , _function . location ( ) , " Constructors cannot be virtual. " ) ;
else if ( _function . annotation ( ) . contract - > isInterface ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . warning ( 5815 _error , _function . location ( ) , " Interface functions are implicitly \" virtual \" " ) ;
2020-06-10 16:19:42 +00:00
else if ( _function . visibility ( ) = = Visibility : : Private )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 3942 _error , _function . location ( ) , " \" virtual \" and \" private \" cannot be used together. " ) ;
2020-06-10 16:19:42 +00:00
else if ( _function . libraryFunction ( ) )
2020-06-10 16:25:19 +00:00
m_errorReporter . typeError ( 7801 _error , _function . location ( ) , " Library functions cannot be \" virtual \" . " ) ;
2019-11-27 13:02:52 +00:00
}
2020-05-04 16:38:00 +00:00
if ( _function . overrides ( ) & & _function . isFree ( ) )
m_errorReporter . syntaxError ( 1750 _error , _function . location ( ) , " Free functions cannot override. " ) ;
2019-11-05 17:25:34 +00:00
2016-08-26 18:37:10 +00:00
if ( _function . isPayable ( ) )
{
2020-06-09 15:56:58 +00:00
if ( _function . libraryFunction ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 7708 _error , _function . location ( ) , " Library functions cannot be payable. " ) ;
2020-05-04 16:38:00 +00:00
else if ( _function . isFree ( ) )
m_errorReporter . typeError ( 9559 _error , _function . location ( ) , " Free functions cannot be payable. " ) ;
else if ( _function . isOrdinary ( ) & & ! _function . isPartOfExternalInterface ( ) )
2020-07-14 13:25:17 +00:00
m_errorReporter . typeError ( 5587 _error , _function . location ( ) , " \" internal \" and \" private \" functions cannot be payable. " ) ;
2016-08-26 18:37:10 +00:00
}
2020-06-18 15:33:36 +00:00
vector < VariableDeclaration const * > internalParametersInConstructor ;
auto checkArgumentAndReturnParameter = [ & ] ( VariableDeclaration const & _var ) {
if ( type ( _var ) - > containsNestedMapping ( ) )
if ( _var . referenceLocation ( ) = = VariableDeclaration : : Location : : Storage )
2020-06-03 10:38:35 +00:00
solAssert (
2020-06-18 15:33:36 +00:00
_function . libraryFunction ( ) | | _function . isConstructor ( ) | | ! _function . isPublic ( ) ,
2020-06-03 10:38:35 +00:00
" Mapping types for parameters or return variables "
" can only be used in internal or library functions. "
) ;
2020-06-18 15:33:36 +00:00
bool functionIsExternallyVisible =
( ! _function . isConstructor ( ) & & _function . isPublic ( ) ) | |
( _function . isConstructor ( ) & & ! m_currentContract - > abstract ( ) ) ;
if (
_function . isConstructor ( ) & &
_var . referenceLocation ( ) = = VariableDeclaration : : Location : : Storage & &
! m_currentContract - > abstract ( )
)
m_errorReporter . typeError (
3644 _error ,
_var . location ( ) ,
" This parameter has a type that can only be used internally. "
" You can make the contract abstract to avoid this problem. "
) ;
else if ( functionIsExternallyVisible )
2018-11-08 10:22:57 +00:00
{
2020-06-18 15:33:36 +00:00
auto iType = type ( _var ) - > interfaceType ( _function . libraryFunction ( ) ) ;
2019-03-07 16:12:10 +00:00
2020-06-03 10:38:35 +00:00
if ( ! iType )
{
2020-06-18 15:33:36 +00:00
string message = iType . message ( ) ;
solAssert ( ! message . empty ( ) , " Expected detailed error message! " ) ;
if ( _function . isConstructor ( ) )
message + = " You can make the contract abstract to avoid this problem. " ;
m_errorReporter . typeError ( 4103 _error , _var . location ( ) , message ) ;
}
else if (
2020-10-22 17:19:14 +00:00
! useABICoderV2 ( ) & &
2020-06-18 15:33:36 +00:00
! typeSupportedByOldABIEncoder ( * type ( _var ) , _function . libraryFunction ( ) )
)
{
string message =
2020-10-29 18:40:17 +00:00
" This type is only supported in ABI coder v2. "
" Use \" pragma abicoder v2; \" to enable the feature. " ;
2020-06-18 15:33:36 +00:00
if ( _function . isConstructor ( ) )
message + =
" Alternatively, make the contract abstract and supply the "
" constructor arguments from a derived contract. " ;
m_errorReporter . typeError (
4957 _error ,
_var . location ( ) ,
message
) ;
2019-03-07 16:12:10 +00:00
}
2018-11-08 10:22:57 +00:00
}
2019-01-17 15:37:36 +00:00
} ;
for ( ASTPointer < VariableDeclaration > const & var : _function . parameters ( ) )
{
checkArgumentAndReturnParameter ( * var ) ;
var - > accept ( * this ) ;
}
for ( ASTPointer < VariableDeclaration > const & var : _function . returnParameters ( ) )
{
checkArgumentAndReturnParameter ( * var ) ;
2017-06-15 15:36:14 +00:00
var - > accept ( * this ) ;
2015-09-16 14:56:30 +00:00
}
2020-06-18 15:33:36 +00:00
2017-06-23 16:55:47 +00:00
set < Declaration const * > modifiers ;
2015-09-16 14:56:30 +00:00
for ( ASTPointer < ModifierInvocation > const & modifier : _function . modifiers ( ) )
2017-06-23 16:55:47 +00:00
{
2020-05-04 16:38:00 +00:00
vector < ContractDefinition const * > baseContracts ;
if ( auto contract = dynamic_cast < ContractDefinition const * > ( _function . scope ( ) ) )
{
baseContracts = contract - > annotation ( ) . linearizedBaseContracts ;
// Delete first base which is just the main contract itself
baseContracts . erase ( baseContracts . begin ( ) ) ;
}
2019-10-22 10:26:26 +00:00
2015-09-16 14:56:30 +00:00
visitManually (
* modifier ,
2019-10-22 10:26:26 +00:00
_function . isConstructor ( ) ? baseContracts : vector < ContractDefinition const * > ( )
2015-09-16 14:56:30 +00:00
) ;
2017-06-23 16:55:47 +00:00
Declaration const * decl = & dereference ( * modifier - > name ( ) ) ;
if ( modifiers . count ( decl ) )
{
if ( dynamic_cast < ContractDefinition const * > ( decl ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . declarationError ( 1697 _error , modifier - > location ( ) , " Base constructor already provided. " ) ;
2017-06-23 16:55:47 +00:00
}
else
modifiers . insert ( decl ) ;
}
2020-05-04 16:38:00 +00:00
solAssert ( _function . isFree ( ) = = ! m_currentContract , " " ) ;
if ( ! m_currentContract )
{
solAssert ( ! _function . isConstructor ( ) , " " ) ;
solAssert ( ! _function . isFallback ( ) , " " ) ;
solAssert ( ! _function . isReceive ( ) , " " ) ;
}
else if ( m_currentContract - > isInterface ( ) )
2017-02-07 22:13:03 +00:00
{
2017-03-17 17:01:13 +00:00
if ( _function . isImplemented ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4726 _error , _function . location ( ) , " Functions in interfaces cannot have an implementation. " ) ;
2018-07-12 12:57:42 +00:00
2017-03-17 17:01:13 +00:00
if ( _function . isConstructor ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6482 _error , _function . location ( ) , " Constructor cannot be defined in interfaces. " ) ;
2020-06-10 16:19:42 +00:00
else if ( _function . visibility ( ) ! = Visibility : : External )
m_errorReporter . typeError ( 1560 _error , _function . location ( ) , " Functions in interfaces must be declared external. " ) ;
2017-03-17 17:01:13 +00:00
}
2020-06-09 16:17:58 +00:00
else if ( m_currentContract - > contractKind ( ) = = ContractKind : : Library )
2017-08-16 21:19:08 +00:00
if ( _function . isConstructor ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 7634 _error , _function . location ( ) , " Constructor cannot be defined in libraries. " ) ;
2020-05-04 16:38:00 +00:00
2017-03-17 17:01:13 +00:00
if ( _function . isImplemented ( ) )
_function . body ( ) . accept ( * this ) ;
2017-08-04 19:38:45 +00:00
else if ( _function . isConstructor ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 5700 _error , _function . location ( ) , " Constructor must be implemented if declared. " ) ;
2020-06-09 15:56:58 +00:00
else if ( _function . libraryFunction ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 9231 _error , _function . location ( ) , " Library functions must be implemented if declared. " ) ;
2019-12-02 20:39:53 +00:00
else if ( ! _function . virtualSemantics ( ) )
2020-05-04 16:38:00 +00:00
{
if ( _function . isFree ( ) )
solAssert ( m_errorReporter . hasErrors ( ) , " " ) ;
else
m_errorReporter . typeError ( 5424 _error , _function . location ( ) , " Functions without implementation must be marked virtual. " ) ;
}
2019-09-09 16:22:02 +00:00
if ( _function . isFallback ( ) )
typeCheckFallbackFunction ( _function ) ;
else if ( _function . isReceive ( ) )
typeCheckReceiveFunction ( _function ) ;
else if ( _function . isConstructor ( ) )
typeCheckConstructor ( _function ) ;
2015-09-16 14:56:30 +00:00
return false ;
}
bool TypeChecker : : visit ( VariableDeclaration const & _variable )
{
2020-07-15 17:50:59 +00:00
_variable . typeName ( ) . accept ( * this ) ;
2019-02-27 10:55:59 +00:00
2015-10-08 16:01:12 +00:00
// type is filled either by ReferencesResolver directly from the type name or by
// TypeChecker at the VariableDeclarationStatement level.
2015-09-16 14:56:30 +00:00
TypePointer varType = _variable . annotation ( ) . type ;
2018-11-28 10:48:51 +00:00
solAssert ( ! ! varType , " Variable type not provided. " ) ;
2018-07-12 14:17:30 +00:00
2017-03-01 18:12:40 +00:00
if ( _variable . value ( ) )
2020-05-19 08:05:15 +00:00
{
2020-06-03 10:38:35 +00:00
if ( _variable . isStateVariable ( ) & & varType - > containsNestedMapping ( ) )
2020-05-19 08:05:15 +00:00
{
2020-06-03 10:38:35 +00:00
m_errorReporter . typeError (
6280 _error ,
_variable . location ( ) ,
" Types in storage containing (nested) mappings cannot be assigned to. "
) ;
2020-05-19 08:05:15 +00:00
_variable . value ( ) - > accept ( * this ) ;
}
else
expectType ( * _variable . value ( ) , * varType ) ;
}
2015-09-16 14:56:30 +00:00
if ( _variable . isConstant ( ) )
{
2017-03-03 18:26:54 +00:00
if ( ! _variable . type ( ) - > isValueType ( ) )
{
bool allowed = false ;
2019-04-15 13:33:39 +00:00
if ( auto arrayType = dynamic_cast < ArrayType const * > ( _variable . type ( ) ) )
2017-09-18 10:31:55 +00:00
allowed = arrayType - > isByteArray ( ) ;
2017-03-03 18:26:54 +00:00
if ( ! allowed )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 9259 _error , _variable . location ( ) , " Constants of non-value type not yet implemented. " ) ;
2017-03-03 18:26:54 +00:00
}
2017-07-08 23:27:28 +00:00
2015-09-16 14:56:30 +00:00
if ( ! _variable . value ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4266 _error , _variable . location ( ) , " Uninitialized \" constant \" variable. " ) ;
2020-09-10 10:01:23 +00:00
else if ( ! * _variable . value ( ) - > annotation ( ) . isPure )
2018-07-03 21:03:26 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
8349 _error ,
2018-07-03 21:03:26 +00:00
_variable . value ( ) - > location ( ) ,
" Initial value for constant variable has to be compile-time constant. "
) ;
2015-09-16 14:56:30 +00:00
}
2020-02-27 15:13:55 +00:00
else if ( _variable . immutable ( ) )
2020-04-03 09:56:51 +00:00
{
2020-02-27 15:13:55 +00:00
if ( ! _variable . type ( ) - > isValueType ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6377 _error , _variable . location ( ) , " Immutable variables cannot have a non-value type. " ) ;
2020-04-03 09:56:51 +00:00
if (
auto const * functionType = dynamic_cast < FunctionType const * > ( _variable . type ( ) ) ;
functionType & & functionType - > kind ( ) = = FunctionType : : Kind : : External
)
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 3366 _error , _variable . location ( ) , " Immutable variables of external function type are not yet supported. " ) ;
2020-04-03 09:56:51 +00:00
solAssert ( _variable . type ( ) - > sizeOnStack ( ) = = 1 | | m_errorReporter . hasErrors ( ) , " " ) ;
}
2020-02-27 15:13:55 +00:00
2015-09-16 14:56:30 +00:00
if ( ! _variable . isStateVariable ( ) )
{
2020-06-03 10:38:35 +00:00
if (
_variable . referenceLocation ( ) = = VariableDeclaration : : Location : : CallData | |
_variable . referenceLocation ( ) = = VariableDeclaration : : Location : : Memory
)
if ( varType - > containsNestedMapping ( ) )
m_errorReporter . fatalTypeError (
4061 _error ,
_variable . location ( ) ,
" Type " + varType - > toString ( true ) + " is only valid in storage because it contains a (nested) mapping. "
) ;
2015-09-16 14:56:30 +00:00
}
2019-12-10 14:54:09 +00:00
else if ( _variable . visibility ( ) > = Visibility : : Public )
2018-11-28 11:17:30 +00:00
{
FunctionType getter ( _variable ) ;
2020-10-22 17:19:14 +00:00
if ( ! useABICoderV2 ( ) )
2018-11-28 11:17:30 +00:00
{
vector < string > unsupportedTypes ;
for ( auto const & param : getter . parameterTypes ( ) + getter . returnParameterTypes ( ) )
2019-02-04 17:13:41 +00:00
if ( ! typeSupportedByOldABIEncoder ( * param , false /* isLibrary */ ) )
2018-11-28 11:17:30 +00:00
unsupportedTypes . emplace_back ( param - > toString ( ) ) ;
if ( ! unsupportedTypes . empty ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError (
2020-05-07 01:52:53 +00:00
2763 _error ,
_variable . location ( ) ,
2020-10-29 18:40:17 +00:00
" The following types are only supported for getters in ABI coder v2: " +
2018-11-28 11:17:30 +00:00
joinHumanReadable ( unsupportedTypes ) +
2020-10-29 18:40:17 +00:00
" . Either remove \" public \" or use \" pragma abicoder v2; \" to enable the feature. "
2018-11-28 11:17:30 +00:00
) ;
}
if ( ! getter . interfaceFunctionType ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6744 _error , _variable . location ( ) , " Internal or recursive type is not allowed for public state variables. " ) ;
2018-11-28 11:17:30 +00:00
}
2017-07-11 20:56:09 +00:00
2020-07-06 19:40:50 +00:00
bool isStructMemberDeclaration = dynamic_cast < StructDefinition const * > ( _variable . scope ( ) ) ! = nullptr ;
if ( isStructMemberDeclaration )
return false ;
2020-04-14 17:03:46 +00:00
if ( auto referenceType = dynamic_cast < ReferenceType const * > ( varType ) )
2018-07-31 09:44:39 +00:00
{
2020-04-14 17:03:46 +00:00
auto result = referenceType - > validForLocation ( referenceType - > location ( ) ) ;
2020-10-06 18:58:46 +00:00
if ( result )
{
bool isLibraryStorageParameter = ( _variable . isLibraryFunctionParameter ( ) & & referenceType - > location ( ) = = DataLocation : : Storage ) ;
bool callDataCheckRequired = ( ( _variable . isConstructorParameter ( ) | | _variable . isPublicCallableParameter ( ) ) & & ! isLibraryStorageParameter ) ;
if ( callDataCheckRequired )
result = referenceType - > validForLocation ( DataLocation : : CallData ) ;
}
2020-04-14 17:03:46 +00:00
if ( ! result )
{
solAssert ( ! result . message ( ) . empty ( ) , " Expected detailed error message " ) ;
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 1534 _error , _variable . location ( ) , result . message ( ) ) ;
2020-07-06 19:40:50 +00:00
return false ;
}
}
2015-09-16 14:56:30 +00:00
return false ;
}
void TypeChecker : : visitManually (
ModifierInvocation const & _modifier ,
vector < ContractDefinition const * > const & _bases
)
{
2018-04-10 09:22:26 +00:00
std : : vector < ASTPointer < Expression > > const & arguments =
_modifier . arguments ( ) ? * _modifier . arguments ( ) : std : : vector < ASTPointer < Expression > > ( ) ;
2015-09-16 14:56:30 +00:00
for ( ASTPointer < Expression > const & argument : arguments )
argument - > accept ( * this ) ;
2019-10-21 11:18:19 +00:00
2019-12-17 15:18:58 +00:00
_modifier . name ( ) - > accept ( * this ) ;
2015-09-16 14:56:30 +00:00
auto const * declaration = & dereference ( * _modifier . name ( ) ) ;
vector < ASTPointer < VariableDeclaration > > emptyParameterList ;
vector < ASTPointer < VariableDeclaration > > const * parameters = nullptr ;
if ( auto modifierDecl = dynamic_cast < ModifierDefinition const * > ( declaration ) )
parameters = & modifierDecl - > parameters ( ) ;
else
// check parameters for Base constructors
for ( ContractDefinition const * base : _bases )
if ( declaration = = base )
{
if ( auto referencedConstructor = base - > constructor ( ) )
parameters = & referencedConstructor - > parameters ( ) ;
else
parameters = & emptyParameterList ;
break ;
}
if ( ! parameters )
2016-01-08 14:20:20 +00:00
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4659 _error , _modifier . location ( ) , " Referenced declaration is neither modifier nor base class. " ) ;
2016-01-08 14:20:20 +00:00
return ;
}
2015-09-16 14:56:30 +00:00
if ( parameters - > size ( ) ! = arguments . size ( ) )
2016-02-11 16:10:35 +00:00
{
2017-05-11 13:26:35 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
2973 _error ,
2015-11-04 10:49:26 +00:00
_modifier . location ( ) ,
2015-09-16 14:56:30 +00:00
" Wrong argument count for modifier invocation: " +
toString ( arguments . size ( ) ) +
" arguments given but expected " +
toString ( parameters - > size ( ) ) +
" . "
) ;
2016-02-11 16:10:35 +00:00
return ;
}
2018-04-10 09:22:26 +00:00
for ( size_t i = 0 ; i < arguments . size ( ) ; + + i )
2019-03-04 17:59:03 +00:00
{
BoolResult result = type ( * arguments [ i ] ) - > isImplicitlyConvertibleTo ( * type ( * ( * parameters ) [ i ] ) ) ;
if ( ! result )
m_errorReporter . typeErrorConcatenateDescriptions (
2020-05-05 22:38:28 +00:00
4649 _error ,
2015-11-04 10:49:26 +00:00
arguments [ i ] - > location ( ) ,
2015-09-16 14:56:30 +00:00
" Invalid type for argument in modifier invocation. "
" Invalid implicit conversion from " +
type ( * arguments [ i ] ) - > toString ( ) +
" to " +
type ( * ( * parameters ) [ i ] ) - > toString ( ) +
2019-03-04 17:59:03 +00:00
" requested. " ,
result . message ( )
2015-09-16 14:56:30 +00:00
) ;
2019-03-04 17:59:03 +00:00
}
2015-09-16 14:56:30 +00:00
}
bool TypeChecker : : visit ( EventDefinition const & _eventDef )
{
2019-12-10 14:54:09 +00:00
solAssert ( _eventDef . visibility ( ) > Visibility : : Internal , " " ) ;
2015-09-16 14:56:30 +00:00
unsigned numIndexed = 0 ;
for ( ASTPointer < VariableDeclaration > const & var : _eventDef . parameters ( ) )
{
if ( var - > isIndexed ( ) )
numIndexed + + ;
2020-06-03 10:38:35 +00:00
if ( type ( * var ) - > containsNestedMapping ( ) )
m_errorReporter . typeError (
3448 _error ,
var - > location ( ) ,
" Type containing a (nested) mapping is not allowed as event parameter type. "
) ;
2019-04-15 13:33:39 +00:00
if ( ! type ( * var ) - > interfaceType ( false ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 3417 _error , var - > location ( ) , " Internal or recursive type is not allowed as event parameter type. " ) ;
2018-08-01 17:01:50 +00:00
if (
2020-10-22 17:19:14 +00:00
! useABICoderV2 ( ) & &
2019-02-04 17:13:41 +00:00
! typeSupportedByOldABIEncoder ( * type ( * var ) , false /* isLibrary */ )
2018-08-01 17:01:50 +00:00
)
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
3061 _error ,
2018-08-01 17:01:50 +00:00
var - > location ( ) ,
2020-10-29 18:40:17 +00:00
" This type is only supported in ABI coder v2. "
" Use \" pragma abicoder v2; \" to enable the feature. "
2018-08-01 17:01:50 +00:00
) ;
2015-09-16 14:56:30 +00:00
}
2017-08-28 20:05:47 +00:00
if ( _eventDef . isAnonymous ( ) & & numIndexed > 4 )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 8598 _error , _eventDef . location ( ) , " More than 4 indexed arguments for anonymous event. " ) ;
2017-08-28 20:05:47 +00:00
else if ( ! _eventDef . isAnonymous ( ) & & numIndexed > 3 )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 7249 _error , _eventDef . location ( ) , " More than 3 indexed arguments for event. " ) ;
2020-07-17 08:49:36 +00:00
return true ;
2015-09-16 14:56:30 +00:00
}
2016-11-11 11:07:30 +00:00
void TypeChecker : : endVisit ( FunctionTypeName const & _funType )
{
FunctionType const & fun = dynamic_cast < FunctionType const & > ( * _funType . annotation ( ) . type ) ;
2017-03-16 11:58:17 +00:00
if ( fun . kind ( ) = = FunctionType : : Kind : : External )
2020-04-14 14:36:37 +00:00
{
for ( auto const & t : _funType . parameterTypes ( ) + _funType . returnParameterTypes ( ) )
{
solAssert ( t - > annotation ( ) . type , " Type not set for parameter. " ) ;
if ( ! t - > annotation ( ) . type - > interfaceType ( false ) . get ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 2582 _error , t - > location ( ) , " Internal type cannot be used for external function type. " ) ;
2020-04-14 14:36:37 +00:00
}
2019-04-15 13:33:39 +00:00
solAssert ( fun . interfaceType ( false ) , " External function type uses internal types. " ) ;
2020-04-14 14:36:37 +00:00
}
2016-11-11 11:07:30 +00:00
}
2016-03-01 21:56:39 +00:00
bool TypeChecker : : visit ( InlineAssembly const & _inlineAssembly )
{
// External references have already been resolved in a prior stage and stored in the annotation.
2017-03-14 14:41:23 +00:00
// We run the resolve step again regardless.
2018-10-15 09:58:51 +00:00
yul : : ExternalIdentifierAccess : : Resolver identifierAccess = [ & ] (
2018-11-21 11:42:34 +00:00
yul : : Identifier const & _identifier ,
2018-10-15 09:58:51 +00:00
yul : : IdentifierContext _context ,
2017-05-24 16:34:19 +00:00
bool
2017-02-23 16:38:42 +00:00
)
{
2016-03-01 21:56:39 +00:00
auto ref = _inlineAssembly . annotation ( ) . externalReferences . find ( & _identifier ) ;
if ( ref = = _inlineAssembly . annotation ( ) . externalReferences . end ( ) )
2020-06-11 16:46:31 +00:00
return false ;
InlineAssemblyAnnotation : : ExternalIdentifierInfo & identifierInfo = ref - > second ;
Declaration const * declaration = identifierInfo . declaration ;
2016-03-01 21:56:39 +00:00
solAssert ( ! ! declaration , " " ) ;
2020-06-11 16:46:31 +00:00
bool requiresStorage = identifierInfo . isSlot | | identifierInfo . isOffset ;
2017-04-11 19:12:17 +00:00
if ( auto var = dynamic_cast < VariableDeclaration const * > ( declaration ) )
{
2019-02-27 16:32:48 +00:00
solAssert ( var - > type ( ) , " Expected variable type! " ) ;
2020-02-27 15:13:55 +00:00
if ( var - > immutable ( ) )
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 3773 _error , _identifier . location , " Assembly access to immutable variables is not supported. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2020-02-27 15:13:55 +00:00
}
2019-07-09 09:11:40 +00:00
if ( var - > isConstant ( ) )
2018-02-19 18:21:33 +00:00
{
2020-03-10 23:32:01 +00:00
var = rootConstVariableDeclaration ( * var ) ;
2019-12-03 00:02:33 +00:00
2020-03-10 23:32:01 +00:00
if ( var & & ! var - > value ( ) )
2019-07-09 09:11:40 +00:00
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 3224 _error , _identifier . location , " Constant has no value. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2019-07-09 09:11:40 +00:00
}
else if ( _context = = yul : : IdentifierContext : : LValue )
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6252 _error , _identifier . location , " Constant variables cannot be assigned to. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2019-07-09 09:11:40 +00:00
}
else if ( requiresStorage )
2019-07-01 13:34:34 +00:00
{
2020-07-01 17:25:14 +00:00
m_errorReporter . typeError ( 6617 _error , _identifier . location , " The suffixes .offset and .slot can only be used on non-constant storage variables. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2019-07-01 13:34:34 +00:00
}
2020-05-28 14:09:52 +00:00
else if ( var & & var - > value ( ) & & ! var - > value ( ) - > annotation ( ) . type & & ! dynamic_cast < Literal const * > ( var - > value ( ) . get ( ) ) )
{
m_errorReporter . typeError (
2249 _error ,
_identifier . location ,
" Constant variables with non-literal values cannot be forward referenced from inline assembly. "
) ;
2020-06-11 16:46:31 +00:00
return false ;
2020-05-28 14:09:52 +00:00
}
else if ( ! var | | ! type ( * var ) - > isValueType ( ) | | (
! dynamic_cast < Literal const * > ( var - > value ( ) . get ( ) ) & &
type ( * var - > value ( ) ) - > category ( ) ! = Type : : Category : : RationalNumber
) )
{
m_errorReporter . typeError ( 7615 _error , _identifier . location , " Only direct number constants and references to such constants are supported by inline assembly. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2020-05-28 14:09:52 +00:00
}
2019-07-09 09:11:40 +00:00
}
2020-05-29 11:51:16 +00:00
solAssert ( ! dynamic_cast < FixedPointType const * > ( var - > type ( ) ) , " FixedPointType not implemented. " ) ;
2019-07-09 09:11:40 +00:00
if ( requiresStorage )
{
if ( ! var - > isStateVariable ( ) & & ! var - > type ( ) - > dataStoredIn ( DataLocation : : Storage ) )
2017-04-21 17:13:46 +00:00
{
2020-07-01 17:25:14 +00:00
m_errorReporter . typeError ( 3622 _error , _identifier . location , " The suffixes .offset and .slot can only be used on storage variables. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2017-04-21 17:13:46 +00:00
}
2020-02-24 14:53:32 +00:00
else if ( _context = = yul : : IdentifierContext : : LValue )
2017-04-21 17:13:46 +00:00
{
2020-02-24 14:53:32 +00:00
if ( var - > isStateVariable ( ) )
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4713 _error , _identifier . location , " State variables cannot be assigned to - you have to use \" sstore() \" . " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2020-02-24 14:53:32 +00:00
}
2020-06-11 16:46:31 +00:00
else if ( identifierInfo . isOffset )
2020-02-24 14:53:32 +00:00
{
2020-07-01 17:25:14 +00:00
m_errorReporter . typeError ( 9739 _error , _identifier . location , " Only .slot can be assigned to. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2020-02-24 14:53:32 +00:00
}
else
2020-06-11 16:46:31 +00:00
solAssert ( identifierInfo . isSlot , " " ) ;
2017-04-21 17:13:46 +00:00
}
}
2019-07-01 13:34:34 +00:00
else if ( ! var - > isConstant ( ) & & var - > isStateVariable ( ) )
2017-04-21 17:13:46 +00:00
{
2020-07-01 17:25:14 +00:00
m_errorReporter . typeError ( 1408 _error , _identifier . location , " Only local variables are supported. To access storage variables, use the .slot and .offset suffixes. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2017-04-11 19:12:17 +00:00
}
2017-04-21 17:13:46 +00:00
else if ( var - > type ( ) - > dataStoredIn ( DataLocation : : Storage ) )
2017-04-11 19:12:17 +00:00
{
2020-07-01 17:25:14 +00:00
m_errorReporter . typeError ( 9068 _error , _identifier . location , " You have to use the .slot or .offset suffix to access storage reference variables. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2017-04-11 19:12:17 +00:00
}
2017-04-21 17:13:46 +00:00
else if ( var - > type ( ) - > sizeOnStack ( ) ! = 1 )
2017-04-11 19:12:17 +00:00
{
2017-07-11 11:37:34 +00:00
if ( var - > type ( ) - > dataStoredIn ( DataLocation : : CallData ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 2370 _error , _identifier . location , " Call data elements cannot be accessed directly. Copy to a local variable first or use \" calldataload \" or \" calldatacopy \" with manually determined offsets and sizes. " ) ;
2017-07-11 11:37:34 +00:00
else
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 9857 _error , _identifier . location , " Only types that use one stack slot are supported. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2017-04-11 19:12:17 +00:00
}
}
2018-08-07 12:17:56 +00:00
else if ( requiresStorage )
{
2020-07-01 17:25:14 +00:00
m_errorReporter . typeError ( 7944 _error , _identifier . location , " The suffixes .offset and .slot can only be used on storage variables. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2018-08-07 12:17:56 +00:00
}
2018-10-15 09:58:51 +00:00
else if ( _context = = yul : : IdentifierContext : : LValue )
2017-04-11 19:12:17 +00:00
{
2019-10-25 02:14:00 +00:00
if ( dynamic_cast < MagicVariableDeclaration const * > ( declaration ) )
2020-06-11 16:46:31 +00:00
return false ;
2019-10-25 02:14:00 +00:00
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 1990 _error , _identifier . location , " Only local variables can be assigned to in inline assembly. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2017-04-11 19:12:17 +00:00
}
2018-10-15 09:58:51 +00:00
if ( _context = = yul : : IdentifierContext : : RValue )
2016-03-01 21:56:39 +00:00
{
solAssert ( ! ! declaration - > type ( ) , " Type of declaration required but not yet determined. " ) ;
if ( dynamic_cast < FunctionDefinition const * > ( declaration ) )
{
2020-05-05 22:38:28 +00:00
m_errorReporter . declarationError ( 2025 _error , _identifier . location , " Access to functions is not allowed in inline assembly. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2017-04-11 19:12:17 +00:00
}
else if ( dynamic_cast < VariableDeclaration const * > ( declaration ) )
{
2016-03-01 21:56:39 +00:00
}
else if ( auto contract = dynamic_cast < ContractDefinition const * > ( declaration ) )
{
if ( ! contract - > isLibrary ( ) )
2017-04-11 19:12:17 +00:00
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4977 _error , _identifier . location , " Expected a library. " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2017-04-11 19:12:17 +00:00
}
2016-03-01 21:56:39 +00:00
}
else
2020-06-11 16:46:31 +00:00
return false ;
2016-03-01 21:56:39 +00:00
}
2020-06-11 16:46:31 +00:00
identifierInfo . valueSize = 1 ;
return true ;
2017-02-23 16:38:42 +00:00
} ;
2017-04-26 13:41:08 +00:00
solAssert ( ! _inlineAssembly . annotation ( ) . analysisInfo , " " ) ;
2018-11-21 11:42:34 +00:00
_inlineAssembly . annotation ( ) . analysisInfo = make_shared < yul : : AsmAnalysisInfo > ( ) ;
yul : : AsmAnalyzer analyzer (
2017-04-26 13:41:08 +00:00
* _inlineAssembly . annotation ( ) . analysisInfo ,
2017-05-11 13:26:35 +00:00
m_errorReporter ,
2019-05-22 11:57:48 +00:00
_inlineAssembly . dialect ( ) ,
2017-04-26 13:41:08 +00:00
identifierAccess
) ;
2017-03-21 18:38:37 +00:00
if ( ! analyzer . analyze ( _inlineAssembly . operations ( ) ) )
2017-02-15 15:47:54 +00:00
return false ;
return true ;
2016-03-01 21:56:39 +00:00
}
2015-09-16 14:56:30 +00:00
bool TypeChecker : : visit ( IfStatement const & _ifStatement )
{
2019-04-17 11:40:50 +00:00
expectType ( _ifStatement . condition ( ) , * TypeProvider : : boolean ( ) ) ;
2015-09-16 14:56:30 +00:00
_ifStatement . trueStatement ( ) . accept ( * this ) ;
if ( _ifStatement . falseStatement ( ) )
_ifStatement . falseStatement ( ) - > accept ( * this ) ;
return false ;
}
2019-09-05 18:02:34 +00:00
void TypeChecker : : endVisit ( TryStatement const & _tryStatement )
{
FunctionCall const * externalCall = dynamic_cast < FunctionCall const * > ( & _tryStatement . externalCall ( ) ) ;
2020-04-08 17:38:30 +00:00
if ( ! externalCall | | * externalCall - > annotation ( ) . kind ! = FunctionCallKind : : FunctionCall )
2019-09-05 18:02:34 +00:00
{
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
5347 _error ,
2019-09-05 18:02:34 +00:00
_tryStatement . externalCall ( ) . location ( ) ,
" Try can only be used with external function calls and contract creation calls. "
) ;
return ;
}
FunctionType const & functionType = dynamic_cast < FunctionType const & > ( * externalCall - > expression ( ) . annotation ( ) . type ) ;
if (
functionType . kind ( ) ! = FunctionType : : Kind : : External & &
functionType . kind ( ) ! = FunctionType : : Kind : : Creation & &
functionType . kind ( ) ! = FunctionType : : Kind : : DelegateCall
)
{
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
2536 _error ,
2019-09-05 18:02:34 +00:00
_tryStatement . externalCall ( ) . location ( ) ,
" Try can only be used with external function calls and contract creation calls. "
) ;
return ;
}
externalCall - > annotation ( ) . tryCall = true ;
solAssert ( _tryStatement . clauses ( ) . size ( ) > = 2 , " " ) ;
solAssert ( _tryStatement . clauses ( ) . front ( ) , " " ) ;
TryCatchClause const & successClause = * _tryStatement . clauses ( ) . front ( ) ;
if ( successClause . parameters ( ) )
{
TypePointers returnTypes =
m_evmVersion . supportsReturndata ( ) ?
functionType . returnParameterTypes ( ) :
functionType . returnParameterTypesWithoutDynamicTypes ( ) ;
std : : vector < ASTPointer < VariableDeclaration > > const & parameters =
successClause . parameters ( ) - > parameters ( ) ;
if ( returnTypes . size ( ) ! = parameters . size ( ) )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
2800 _error ,
2019-09-05 18:02:34 +00:00
successClause . location ( ) ,
" Function returns " +
to_string ( functionType . returnParameterTypes ( ) . size ( ) ) +
" values, but returns clause has " +
to_string ( parameters . size ( ) ) +
" variables. "
) ;
size_t len = min ( returnTypes . size ( ) , parameters . size ( ) ) ;
for ( size_t i = 0 ; i < len ; + + i )
{
solAssert ( returnTypes [ i ] , " " ) ;
if ( parameters [ i ] & & * parameters [ i ] - > annotation ( ) . type ! = * returnTypes [ i ] )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
6509 _error ,
2019-09-05 18:02:34 +00:00
parameters [ i ] - > location ( ) ,
" Invalid type, expected " +
returnTypes [ i ] - > toString ( false ) +
" but got " +
parameters [ i ] - > annotation ( ) . type - > toString ( ) +
" . "
) ;
}
}
TryCatchClause const * errorClause = nullptr ;
TryCatchClause const * lowLevelClause = nullptr ;
for ( size_t i = 1 ; i < _tryStatement . clauses ( ) . size ( ) ; + + i )
{
TryCatchClause const & clause = * _tryStatement . clauses ( ) [ i ] ;
if ( clause . errorName ( ) = = " " )
{
if ( lowLevelClause )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
5320 _error ,
2019-09-05 18:02:34 +00:00
clause . location ( ) ,
SecondarySourceLocation { } . append ( " The first clause is here: " , lowLevelClause - > location ( ) ) ,
" This try statement already has a low-level catch clause. "
) ;
lowLevelClause = & clause ;
if ( clause . parameters ( ) & & ! clause . parameters ( ) - > parameters ( ) . empty ( ) )
{
if (
clause . parameters ( ) - > parameters ( ) . size ( ) ! = 1 | |
* clause . parameters ( ) - > parameters ( ) . front ( ) - > type ( ) ! = * TypeProvider : : bytesMemory ( )
)
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6231 _error , clause . location ( ) , " Expected `catch (bytes memory ...) { ... }` or `catch { ... }`. " ) ;
2019-09-05 18:02:34 +00:00
if ( ! m_evmVersion . supportsReturndata ( ) )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
9908 _error ,
2019-09-05 18:02:34 +00:00
clause . location ( ) ,
" This catch clause type cannot be used on the selected EVM version ( " +
m_evmVersion . name ( ) +
" ). You need at least a Byzantium-compatible EVM or use `catch { ... }`. "
) ;
}
}
else if ( clause . errorName ( ) = = " Error " )
{
if ( ! m_evmVersion . supportsReturndata ( ) )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
1812 _error ,
2019-09-05 18:02:34 +00:00
clause . location ( ) ,
" This catch clause type cannot be used on the selected EVM version ( " +
m_evmVersion . name ( ) +
" ). You need at least a Byzantium-compatible EVM or use `catch { ... }`. "
) ;
if ( errorClause )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
1036 _error ,
2019-09-05 18:02:34 +00:00
clause . location ( ) ,
SecondarySourceLocation { } . append ( " The first clause is here: " , errorClause - > location ( ) ) ,
" This try statement already has an \" Error \" catch clause. "
) ;
errorClause = & clause ;
if (
! clause . parameters ( ) | |
clause . parameters ( ) - > parameters ( ) . size ( ) ! = 1 | |
* clause . parameters ( ) - > parameters ( ) . front ( ) - > type ( ) ! = * TypeProvider : : stringMemory ( )
)
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 2943 _error , clause . location ( ) , " Expected `catch Error(string memory ...) { ... }`. " ) ;
2019-09-05 18:02:34 +00:00
}
else
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
3542 _error ,
2019-09-05 18:02:34 +00:00
clause . location ( ) ,
" Invalid catch clause name. Expected either `catch (...)` or `catch Error(...)`. "
) ;
}
}
2015-09-16 14:56:30 +00:00
bool TypeChecker : : visit ( WhileStatement const & _whileStatement )
{
2019-04-17 11:40:50 +00:00
expectType ( _whileStatement . condition ( ) , * TypeProvider : : boolean ( ) ) ;
2015-09-16 14:56:30 +00:00
_whileStatement . body ( ) . accept ( * this ) ;
return false ;
}
bool TypeChecker : : visit ( ForStatement const & _forStatement )
{
if ( _forStatement . initializationExpression ( ) )
_forStatement . initializationExpression ( ) - > accept ( * this ) ;
if ( _forStatement . condition ( ) )
2019-04-17 11:40:50 +00:00
expectType ( * _forStatement . condition ( ) , * TypeProvider : : boolean ( ) ) ;
2015-09-16 14:56:30 +00:00
if ( _forStatement . loopExpression ( ) )
_forStatement . loopExpression ( ) - > accept ( * this ) ;
_forStatement . body ( ) . accept ( * this ) ;
return false ;
}
void TypeChecker : : endVisit ( Return const & _return )
{
2018-08-07 18:47:23 +00:00
ParameterList const * params = _return . annotation ( ) . functionReturnParameters ;
2015-09-16 14:56:30 +00:00
if ( ! _return . expression ( ) )
2018-08-07 18:47:23 +00:00
{
if ( params & & ! params - > parameters ( ) . empty ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6777 _error , _return . location ( ) , " Return arguments required. " ) ;
2015-09-16 14:56:30 +00:00
return ;
2018-08-07 18:47:23 +00:00
}
2015-09-16 14:56:30 +00:00
if ( ! params )
2015-10-12 21:02:35 +00:00
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 7552 _error , _return . location ( ) , " Return arguments not allowed. " ) ;
2015-10-12 21:02:35 +00:00
return ;
}
TypePointers returnTypes ;
for ( auto const & var : params - > parameters ( ) )
returnTypes . push_back ( type ( * var ) ) ;
2019-04-15 13:33:39 +00:00
if ( auto tupleType = dynamic_cast < TupleType const * > ( type ( * _return . expression ( ) ) ) )
2015-10-12 21:02:35 +00:00
{
if ( tupleType - > components ( ) . size ( ) ! = params - > parameters ( ) . size ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 5132 _error , _return . location ( ) , " Different number of arguments in return statement than in returns declaration. " ) ;
2019-03-04 17:59:03 +00:00
else
{
BoolResult result = tupleType - > isImplicitlyConvertibleTo ( TupleType ( returnTypes ) ) ;
if ( ! result )
m_errorReporter . typeErrorConcatenateDescriptions (
2020-05-05 22:38:28 +00:00
5992 _error ,
2019-03-04 17:59:03 +00:00
_return . expression ( ) - > location ( ) ,
" Return argument type " +
type ( * _return . expression ( ) ) - > toString ( ) +
" is not implicitly convertible to expected type " +
TupleType ( returnTypes ) . toString ( false ) + " . " ,
result . message ( )
) ;
}
2015-10-12 21:02:35 +00:00
}
2015-09-16 14:56:30 +00:00
else if ( params - > parameters ( ) . size ( ) ! = 1 )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 8863 _error , _return . location ( ) , " Different number of arguments in return statement than in returns declaration. " ) ;
2015-09-16 14:56:30 +00:00
else
{
TypePointer const & expected = type ( * params - > parameters ( ) . front ( ) ) ;
2019-03-04 17:59:03 +00:00
BoolResult result = type ( * _return . expression ( ) ) - > isImplicitlyConvertibleTo ( * expected ) ;
if ( ! result )
m_errorReporter . typeErrorConcatenateDescriptions (
2020-05-05 22:38:28 +00:00
6359 _error ,
2015-11-04 10:49:26 +00:00
_return . expression ( ) - > location ( ) ,
2015-09-16 14:56:30 +00:00
" Return argument type " +
type ( * _return . expression ( ) ) - > toString ( ) +
" is not implicitly convertible to expected type (type of first return variable) " +
2019-03-04 17:59:03 +00:00
expected - > toString ( ) + " . " ,
result . message ( )
2015-09-16 14:56:30 +00:00
) ;
}
}
2018-02-16 15:55:21 +00:00
void TypeChecker : : endVisit ( EmitStatement const & _emit )
{
if (
2020-04-08 17:38:30 +00:00
* _emit . eventCall ( ) . annotation ( ) . kind ! = FunctionCallKind : : FunctionCall | |
2018-05-04 04:21:28 +00:00
type ( _emit . eventCall ( ) . expression ( ) ) - > category ( ) ! = Type : : Category : : Function | |
2018-02-16 15:55:21 +00:00
dynamic_cast < FunctionType const & > ( * type ( _emit . eventCall ( ) . expression ( ) ) ) . kind ( ) ! = FunctionType : : Kind : : Event
)
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 9292 _error , _emit . eventCall ( ) . expression ( ) . location ( ) , " Expression has to be an event invocation. " ) ;
2018-02-16 15:55:21 +00:00
}
2015-10-08 16:01:12 +00:00
bool TypeChecker : : visit ( VariableDeclarationStatement const & _statement )
{
2015-10-09 17:35:41 +00:00
if ( ! _statement . initialValue ( ) )
2015-10-08 16:01:12 +00:00
{
2015-10-09 17:35:41 +00:00
// No initial value is only permitted for single variables with specified type.
2020-07-15 17:50:59 +00:00
// This usually already results in a parser error.
2015-10-09 17:35:41 +00:00
if ( _statement . declarations ( ) . size ( ) ! = 1 | | ! _statement . declarations ( ) . front ( ) )
2018-07-12 14:17:30 +00:00
{
2020-07-15 17:50:59 +00:00
solAssert ( m_errorReporter . hasErrors ( ) , " " ) ;
2018-07-12 14:17:30 +00:00
2020-07-15 17:50:59 +00:00
// It is okay to return here, as there are no named components on the
// left-hand-side that could cause any damage later.
return false ;
2018-07-12 14:17:30 +00:00
}
2015-10-09 17:35:41 +00:00
VariableDeclaration const & varDecl = * _statement . declarations ( ) . front ( ) ;
2020-07-15 17:50:59 +00:00
solAssert ( varDecl . annotation ( ) . type , " " ) ;
2018-07-12 14:17:30 +00:00
2020-04-02 06:57:38 +00:00
if ( dynamic_cast < MappingType const * > ( type ( varDecl ) ) )
2017-05-11 13:26:35 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
4182 _error ,
2017-03-03 17:44:35 +00:00
varDecl . location ( ) ,
" Uninitialized mapping. Mappings cannot be created dynamically, you have to assign them from a state variable. "
) ;
2015-10-09 17:35:41 +00:00
varDecl . accept ( * this ) ;
2015-10-08 16:01:12 +00:00
return false ;
}
2015-10-09 17:35:41 +00:00
// Here we have an initial value and might have to derive some types before we can visit
// the variable declaration(s).
_statement . initialValue ( ) - > accept ( * this ) ;
2015-10-09 18:44:56 +00:00
TypePointers valueTypes ;
2019-04-15 13:33:39 +00:00
if ( auto tupleType = dynamic_cast < TupleType const * > ( type ( * _statement . initialValue ( ) ) ) )
2015-10-09 18:44:56 +00:00
valueTypes = tupleType - > components ( ) ;
else
2015-10-12 21:02:35 +00:00
valueTypes = TypePointers { type ( * _statement . initialValue ( ) ) } ;
2015-10-09 17:35:41 +00:00
2015-10-09 18:44:56 +00:00
vector < ASTPointer < VariableDeclaration > > const & variables = _statement . declarations ( ) ;
2015-10-13 12:31:24 +00:00
if ( variables . empty ( ) )
2018-07-04 16:34:24 +00:00
// We already have an error for this in the SyntaxChecker.
solAssert ( m_errorReporter . hasErrors ( ) , " " ) ;
2018-05-03 17:21:42 +00:00
else if ( valueTypes . size ( ) ! = variables . size ( ) )
2018-07-04 16:34:24 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
7364 _error ,
2015-11-04 10:49:26 +00:00
_statement . location ( ) ,
2018-07-04 16:34:24 +00:00
" Different number of components on the left hand side ( " +
toString ( variables . size ( ) ) +
" ) than on the right hand side ( " +
2015-10-09 18:44:56 +00:00
toString ( valueTypes . size ( ) ) +
2018-07-04 16:34:24 +00:00
" ). "
2015-10-09 18:44:56 +00:00
) ;
2015-10-09 17:35:41 +00:00
2018-07-04 16:34:24 +00:00
for ( size_t i = 0 ; i < min ( variables . size ( ) , valueTypes . size ( ) ) ; + + i )
2015-10-09 17:35:41 +00:00
{
2018-07-04 16:34:24 +00:00
if ( ! variables [ i ] )
2015-10-09 17:35:41 +00:00
continue ;
2018-07-04 16:34:24 +00:00
VariableDeclaration const & var = * variables [ i ] ;
2015-10-09 17:35:41 +00:00
solAssert ( ! var . value ( ) , " Value has to be tied to statement. " ) ;
2015-10-09 18:44:56 +00:00
TypePointer const & valueComponentType = valueTypes [ i ] ;
2015-10-09 17:35:41 +00:00
solAssert ( ! ! valueComponentType , " " ) ;
2020-07-15 17:50:59 +00:00
solAssert ( var . annotation ( ) . type , " " ) ;
2017-06-22 14:08:59 +00:00
2020-07-15 17:50:59 +00:00
var . accept ( * this ) ;
BoolResult result = valueComponentType - > isImplicitlyConvertibleTo ( * var . annotation ( ) . type ) ;
if ( ! result )
2015-10-09 17:35:41 +00:00
{
2020-07-15 17:50:59 +00:00
auto errorMsg = " Type " +
valueComponentType - > toString ( ) +
" is not implicitly convertible to expected type " +
var . annotation ( ) . type - > toString ( ) ;
if (
valueComponentType - > category ( ) = = Type : : Category : : RationalNumber & &
dynamic_cast < RationalNumberType const & > ( * valueComponentType ) . isFractional ( ) & &
valueComponentType - > mobileType ( )
)
2016-05-05 22:47:08 +00:00
{
2020-07-15 17:50:59 +00:00
if ( var . annotation ( ) . type - > operator = = ( * valueComponentType - > mobileType ( ) ) )
m_errorReporter . typeError (
5107 _error ,
_statement . location ( ) ,
errorMsg + " , but it can be explicitly converted. "
) ;
2016-05-05 22:47:08 +00:00
else
2020-07-15 17:50:59 +00:00
m_errorReporter . typeError (
4486 _error ,
2019-03-04 17:59:03 +00:00
_statement . location ( ) ,
2020-07-15 17:50:59 +00:00
errorMsg +
" . Try converting to type " +
valueComponentType - > mobileType ( ) - > toString ( ) +
" or use an explicit conversion. "
2019-03-04 17:59:03 +00:00
) ;
2016-05-05 22:47:08 +00:00
}
2020-07-15 17:50:59 +00:00
else
m_errorReporter . typeErrorConcatenateDescriptions (
9574 _error ,
_statement . location ( ) ,
errorMsg + " . " ,
result . message ( )
) ;
2015-10-09 17:35:41 +00:00
}
2015-10-08 16:01:12 +00:00
}
2018-07-02 15:00:09 +00:00
2019-02-27 16:32:48 +00:00
if ( valueTypes . size ( ) ! = variables . size ( ) )
{
solAssert ( m_errorReporter . hasErrors ( ) , " Should have errors! " ) ;
for ( auto const & var : variables )
if ( var & & ! var - > annotation ( ) . type )
BOOST_THROW_EXCEPTION ( FatalError ( ) ) ;
}
2015-10-08 16:01:12 +00:00
return false ;
}
2015-09-16 14:56:30 +00:00
void TypeChecker : : endVisit ( ExpressionStatement const & _statement )
{
2016-03-29 20:08:51 +00:00
if ( type ( _statement . expression ( ) ) - > category ( ) = = Type : : Category : : RationalNumber )
2016-05-10 08:26:53 +00:00
if ( ! dynamic_cast < RationalNumberType const & > ( * type ( _statement . expression ( ) ) ) . mobileType ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 3757 _error , _statement . expression ( ) . location ( ) , " Invalid rational number. " ) ;
2016-06-21 12:36:23 +00:00
2016-06-24 14:41:17 +00:00
if ( auto call = dynamic_cast < FunctionCall const * > ( & _statement . expression ( ) ) )
{
2019-04-15 13:33:39 +00:00
if ( auto callType = dynamic_cast < FunctionType const * > ( type ( call - > expression ( ) ) ) )
2016-06-24 14:41:17 +00:00
{
2017-03-16 11:58:17 +00:00
auto kind = callType - > kind ( ) ;
2016-06-24 14:41:17 +00:00
if (
2017-08-01 09:32:23 +00:00
kind = = FunctionType : : Kind : : BareCall | |
2017-03-16 11:58:17 +00:00
kind = = FunctionType : : Kind : : BareCallCode | |
2018-08-15 12:40:20 +00:00
kind = = FunctionType : : Kind : : BareDelegateCall | |
kind = = FunctionType : : Kind : : BareStaticCall
2016-06-24 14:41:17 +00:00
)
2020-05-05 22:38:28 +00:00
m_errorReporter . warning ( 9302 _error , _statement . location ( ) , " Return value of low-level calls not used. " ) ;
2017-03-16 11:58:17 +00:00
else if ( kind = = FunctionType : : Kind : : Send )
2020-05-05 22:38:28 +00:00
m_errorReporter . warning ( 5878 _error , _statement . location ( ) , " Failure condition of 'send' ignored. Consider using 'transfer' instead. " ) ;
2016-06-24 14:41:17 +00:00
}
}
2015-09-16 14:56:30 +00:00
}
2016-01-07 09:01:46 +00:00
bool TypeChecker : : visit ( Conditional const & _conditional )
2015-12-22 16:50:06 +00:00
{
2019-04-17 11:40:50 +00:00
expectType ( _conditional . condition ( ) , * TypeProvider : : boolean ( ) ) ;
2015-12-23 16:12:41 +00:00
2016-01-11 07:08:28 +00:00
_conditional . trueExpression ( ) . accept ( * this ) ;
_conditional . falseExpression ( ) . accept ( * this ) ;
2016-01-07 09:01:46 +00:00
2016-01-11 16:00:14 +00:00
TypePointer trueType = type ( _conditional . trueExpression ( ) ) - > mobileType ( ) ;
TypePointer falseType = type ( _conditional . falseExpression ( ) ) - > mobileType ( ) ;
2019-02-06 19:42:38 +00:00
2019-04-15 13:33:39 +00:00
TypePointer commonType = nullptr ;
2019-02-06 19:42:38 +00:00
2016-10-21 10:30:58 +00:00
if ( ! trueType )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 9717 _error , _conditional . trueExpression ( ) . location ( ) , " Invalid mobile type in true expression. " ) ;
2019-02-06 19:42:38 +00:00
else
commonType = trueType ;
2016-10-21 10:30:58 +00:00
if ( ! falseType )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 3703 _error , _conditional . falseExpression ( ) . location ( ) , " Invalid mobile type in false expression. " ) ;
2019-02-06 19:42:38 +00:00
else
commonType = falseType ;
2016-01-07 09:01:46 +00:00
2019-02-06 19:42:38 +00:00
if ( ! trueType & & ! falseType )
BOOST_THROW_EXCEPTION ( FatalError ( ) ) ;
else if ( trueType & & falseType )
2016-01-07 09:01:46 +00:00
{
2019-02-06 19:42:38 +00:00
commonType = Type : : commonType ( trueType , falseType ) ;
if ( ! commonType )
{
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
1080 _error ,
2019-02-06 19:42:38 +00:00
_conditional . location ( ) ,
" True expression's type " +
trueType - > toString ( ) +
2020-07-06 11:44:33 +00:00
" does not match false expression's type " +
2019-02-06 19:42:38 +00:00
falseType - > toString ( ) +
" . "
) ;
// even we can't find a common type, we have to set a type here,
// otherwise the upper statement will not be able to check the type.
commonType = trueType ;
}
2016-01-11 07:08:28 +00:00
}
2016-01-07 09:01:46 +00:00
2020-09-10 10:01:23 +00:00
_conditional . annotation ( ) . isConstant = false ;
2016-01-11 07:08:28 +00:00
_conditional . annotation ( ) . type = commonType ;
2017-03-01 18:12:40 +00:00
_conditional . annotation ( ) . isPure =
2020-09-10 10:01:23 +00:00
* _conditional . condition ( ) . annotation ( ) . isPure & &
* _conditional . trueExpression ( ) . annotation ( ) . isPure & &
* _conditional . falseExpression ( ) . annotation ( ) . isPure ;
_conditional . annotation ( ) . isLValue = false ;
2016-01-07 09:01:46 +00:00
2020-04-09 10:48:57 +00:00
if ( _conditional . annotation ( ) . willBeWrittenTo )
2017-05-11 13:26:35 +00:00
m_errorReporter . typeError (
2020-07-15 14:27:38 +00:00
2212 _error ,
_conditional . location ( ) ,
" Conditional expression as left value is not supported yet. "
2016-01-11 07:08:28 +00:00
) ;
2016-01-07 09:01:46 +00:00
return false ;
2015-12-22 16:50:06 +00:00
}
2018-08-03 12:32:37 +00:00
void TypeChecker : : checkExpressionAssignment ( Type const & _type , Expression const & _expression )
{
if ( auto const * tupleExpression = dynamic_cast < TupleExpression const * > ( & _expression ) )
{
2020-04-23 05:02:04 +00:00
if ( tupleExpression - > components ( ) . empty ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 5547 _error , _expression . location ( ) , " Empty tuple on the left hand side. " ) ;
2020-04-23 05:02:04 +00:00
2018-08-03 15:38:06 +00:00
auto const * tupleType = dynamic_cast < TupleType const * > ( & _type ) ;
2020-04-23 03:48:02 +00:00
auto const & types = tupleType & & tupleExpression - > components ( ) . size ( ) ! = 1 ? tupleType - > components ( ) : vector < TypePointer > { & _type } ;
2018-08-03 15:38:06 +00:00
2018-10-05 13:38:14 +00:00
solAssert (
tupleExpression - > components ( ) . size ( ) = = types . size ( ) | | m_errorReporter . hasErrors ( ) ,
2020-03-30 13:18:51 +00:00
" Array sizes don't match and no errors generated. "
2018-10-05 13:38:14 +00:00
) ;
for ( size_t i = 0 ; i < min ( tupleExpression - > components ( ) . size ( ) , types . size ( ) ) ; i + + )
2018-08-03 15:38:06 +00:00
if ( types [ i ] )
{
solAssert ( ! ! tupleExpression - > components ( ) [ i ] , " " ) ;
checkExpressionAssignment ( * types [ i ] , * tupleExpression - > components ( ) [ i ] ) ;
}
2018-08-03 12:32:37 +00:00
}
2020-06-03 10:38:35 +00:00
else if ( _type . nameable ( ) & & _type . containsNestedMapping ( ) )
2018-08-03 14:22:03 +00:00
{
bool isLocalOrReturn = false ;
if ( auto const * identifier = dynamic_cast < Identifier const * > ( & _expression ) )
if ( auto const * variableDeclaration = dynamic_cast < VariableDeclaration const * > ( identifier - > annotation ( ) . referencedDeclaration ) )
if ( variableDeclaration - > isLocalOrReturn ( ) )
isLocalOrReturn = true ;
if ( ! isLocalOrReturn )
2020-06-03 10:38:35 +00:00
m_errorReporter . typeError ( 9214 _error , _expression . location ( ) , " Types in storage containing (nested) mappings cannot be assigned to. " ) ;
2018-08-03 14:22:03 +00:00
}
2018-08-03 12:32:37 +00:00
}
2015-09-16 14:56:30 +00:00
bool TypeChecker : : visit ( Assignment const & _assignment )
{
2020-03-10 17:15:50 +00:00
requireLValue (
_assignment . leftHandSide ( ) ,
_assignment . assignmentOperator ( ) = = Token : : Assign
) ;
2015-09-16 14:56:30 +00:00
TypePointer t = type ( _assignment . leftHandSide ( ) ) ;
_assignment . annotation ( ) . type = t ;
2020-09-10 10:01:23 +00:00
_assignment . annotation ( ) . isPure = false ;
_assignment . annotation ( ) . isLValue = false ;
_assignment . annotation ( ) . isConstant = false ;
2018-08-03 12:32:37 +00:00
checkExpressionAssignment ( * t , _assignment . leftHandSide ( ) ) ;
2019-04-15 13:33:39 +00:00
if ( TupleType const * tupleType = dynamic_cast < TupleType const * > ( t ) )
2015-10-14 13:19:50 +00:00
{
2017-03-06 13:50:00 +00:00
if ( _assignment . assignmentOperator ( ) ! = Token : : Assign )
2017-05-11 13:26:35 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
4289 _error ,
2017-03-06 13:50:00 +00:00
_assignment . location ( ) ,
" Compound assignment is not allowed for tuple types. "
) ;
2015-10-15 14:02:00 +00:00
// Sequenced assignments of tuples is not valid, make the result a "void" type.
2019-04-17 11:40:50 +00:00
_assignment . annotation ( ) . type = TypeProvider : : emptyTuple ( ) ;
2018-05-03 17:21:42 +00:00
2015-10-14 13:19:50 +00:00
expectType ( _assignment . rightHandSide ( ) , * tupleType ) ;
2017-06-21 17:32:56 +00:00
2017-07-26 12:19:46 +00:00
// expectType does not cause fatal errors, so we have to check again here.
2019-04-15 13:33:39 +00:00
if ( dynamic_cast < TupleType const * > ( type ( _assignment . rightHandSide ( ) ) ) )
2017-07-26 12:19:46 +00:00
checkDoubleStorageAssignment ( _assignment ) ;
2015-10-14 13:19:50 +00:00
}
2015-09-16 14:56:30 +00:00
else if ( _assignment . assignmentOperator ( ) = = Token : : Assign )
expectType ( _assignment . rightHandSide ( ) , * t ) ;
else
{
// compound assignment
_assignment . rightHandSide ( ) . accept ( * this ) ;
TypePointer resultType = t - > binaryOperatorResult (
2018-10-22 14:48:21 +00:00
TokenTraits : : AssignmentToBinaryOp ( _assignment . assignmentOperator ( ) ) ,
2015-09-16 14:56:30 +00:00
type ( _assignment . rightHandSide ( ) )
) ;
if ( ! resultType | | * resultType ! = * t )
2017-05-11 13:26:35 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
7366 _error ,
2015-11-04 10:49:26 +00:00
_assignment . location ( ) ,
2015-09-16 14:56:30 +00:00
" Operator " +
2018-10-22 14:48:21 +00:00
string ( TokenTraits : : toString ( _assignment . assignmentOperator ( ) ) ) +
2015-09-16 14:56:30 +00:00
" not compatible with types " +
t - > toString ( ) +
" and " +
type ( _assignment . rightHandSide ( ) ) - > toString ( )
) ;
}
return false ;
}
2015-10-12 21:02:35 +00:00
bool TypeChecker : : visit ( TupleExpression const & _tuple )
{
2020-09-10 10:01:23 +00:00
_tuple . annotation ( ) . isConstant = false ;
2015-10-12 21:02:35 +00:00
vector < ASTPointer < Expression > > const & components = _tuple . components ( ) ;
TypePointers types ;
2016-01-11 20:25:59 +00:00
2020-04-09 10:48:57 +00:00
if ( _tuple . annotation ( ) . willBeWrittenTo )
2015-10-12 21:02:35 +00:00
{
2016-01-11 20:25:59 +00:00
if ( _tuple . isInlineArray ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 3025 _error , _tuple . location ( ) , " Inline array type cannot be declared as LValue. " ) ;
2015-10-12 21:02:35 +00:00
for ( auto const & component : components )
if ( component )
{
2020-03-10 17:15:50 +00:00
requireLValue (
* component ,
2020-10-05 10:21:30 +00:00
_tuple . annotation ( ) . lValueOfOrdinaryAssignment
2020-03-10 17:15:50 +00:00
) ;
2015-10-12 21:02:35 +00:00
types . push_back ( type ( * component ) ) ;
}
else
types . push_back ( TypePointer ( ) ) ;
2016-01-04 08:11:04 +00:00
if ( components . size ( ) = = 1 )
_tuple . annotation ( ) . type = type ( * components [ 0 ] ) ;
else
2019-04-17 11:40:50 +00:00
_tuple . annotation ( ) . type = TypeProvider : : tuple ( move ( types ) ) ;
2015-10-12 21:02:35 +00:00
// If some of the components are not LValues, the error is reported above.
_tuple . annotation ( ) . isLValue = true ;
2020-09-10 10:01:23 +00:00
_tuple . annotation ( ) . isPure = false ;
2015-10-12 21:02:35 +00:00
}
else
{
2017-03-01 18:12:40 +00:00
bool isPure = true ;
2019-04-15 13:33:39 +00:00
TypePointer inlineArrayType = nullptr ;
2018-04-23 14:20:37 +00:00
2015-10-12 21:02:35 +00:00
for ( size_t i = 0 ; i < components . size ( ) ; + + i )
{
2018-07-10 10:37:09 +00:00
if ( ! components [ i ] )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 8381 _error , _tuple . location ( ) , " Tuple component cannot be empty. " ) ;
2018-04-22 14:54:33 +00:00
2020-04-08 21:40:29 +00:00
components [ i ] - > accept ( * this ) ;
types . push_back ( type ( * components [ i ] ) ) ;
2017-09-18 10:39:17 +00:00
2020-04-08 21:40:29 +00:00
if ( types [ i ] - > category ( ) = = Type : : Category : : Tuple )
if ( dynamic_cast < TupleType const & > ( * types [ i ] ) . components ( ) . empty ( ) )
2016-10-21 10:30:58 +00:00
{
2020-04-08 21:40:29 +00:00
if ( _tuple . isInlineArray ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 5604 _error , components [ i ] - > location ( ) , " Array component cannot be empty. " ) ;
m_errorReporter . typeError ( 6473 _error , components [ i ] - > location ( ) , " Tuple component cannot be empty. " ) ;
2020-04-08 21:40:29 +00:00
}
2019-02-07 14:53:49 +00:00
2020-04-08 21:40:29 +00:00
// Note: code generation will visit each of the expression even if they are not assigned from.
if ( types [ i ] - > category ( ) = = Type : : Category : : RationalNumber & & components . size ( ) > 1 )
if ( ! dynamic_cast < RationalNumberType const & > ( * types [ i ] ) . mobileType ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 3390 _error , components [ i ] - > location ( ) , " Invalid rational number. " ) ;
2016-10-21 10:30:58 +00:00
2020-04-08 21:40:29 +00:00
if ( _tuple . isInlineArray ( ) )
{
solAssert ( ! ! types [ i ] , " Inline array cannot have empty components " ) ;
if ( ( i = = 0 | | inlineArrayType ) & & ! types [ i ] - > mobileType ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 9563 _error , components [ i ] - > location ( ) , " Invalid mobile type. " ) ;
2020-04-08 21:40:29 +00:00
if ( i = = 0 )
inlineArrayType = types [ i ] - > mobileType ( ) ;
else if ( inlineArrayType )
inlineArrayType = Type : : commonType ( inlineArrayType , types [ i ] ) ;
2015-10-12 21:02:35 +00:00
}
2020-09-10 10:01:23 +00:00
if ( ! * components [ i ] - > annotation ( ) . isPure )
2020-04-08 21:40:29 +00:00
isPure = false ;
2015-10-12 21:02:35 +00:00
}
2017-03-01 18:12:40 +00:00
_tuple . annotation ( ) . isPure = isPure ;
2016-01-11 20:25:59 +00:00
if ( _tuple . isInlineArray ( ) )
{
2017-10-05 13:28:25 +00:00
if ( ! inlineArrayType )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 6378 _error , _tuple . location ( ) , " Unable to deduce common type for array elements. " ) ;
2020-05-26 13:20:54 +00:00
else if ( ! inlineArrayType - > nameable ( ) )
m_errorReporter . fatalTypeError (
9656 _error ,
_tuple . location ( ) ,
" Unable to deduce nameable type for array elements. Try adding explicit type conversion for the first element. "
) ;
2020-06-03 10:38:35 +00:00
else if ( inlineArrayType - > containsNestedMapping ( ) )
m_errorReporter . fatalTypeError (
1545 _error ,
_tuple . location ( ) ,
" Type " + inlineArrayType - > toString ( true ) + " is only valid in storage. "
) ;
2018-11-29 18:44:33 +00:00
2019-04-17 11:40:50 +00:00
_tuple . annotation ( ) . type = TypeProvider : : array ( DataLocation : : Memory , inlineArrayType , types . size ( ) ) ;
2016-01-11 20:25:59 +00:00
}
2015-10-12 21:02:35 +00:00
else
{
2016-01-11 20:25:59 +00:00
if ( components . size ( ) = = 1 )
_tuple . annotation ( ) . type = type ( * components [ 0 ] ) ;
else
2019-04-17 11:40:50 +00:00
_tuple . annotation ( ) . type = TypeProvider : : tuple ( move ( types ) ) ;
2015-10-12 21:02:35 +00:00
}
2016-01-11 20:25:59 +00:00
2020-09-10 10:01:23 +00:00
_tuple . annotation ( ) . isLValue = false ;
2015-10-12 21:02:35 +00:00
}
return false ;
}
2015-09-16 14:56:30 +00:00
bool TypeChecker : : visit ( UnaryOperation const & _operation )
{
// Inc, Dec, Add, Sub, Not, BitNot, Delete
2018-10-22 14:48:21 +00:00
Token op = _operation . getOperator ( ) ;
bool const modifying = ( op = = Token : : Inc | | op = = Token : : Dec | | op = = Token : : Delete ) ;
2017-03-01 18:12:40 +00:00
if ( modifying )
2020-03-10 17:15:50 +00:00
requireLValue ( _operation . subExpression ( ) , false ) ;
2015-09-16 14:56:30 +00:00
else
_operation . subExpression ( ) . accept ( * this ) ;
TypePointer const & subExprType = type ( _operation . subExpression ( ) ) ;
TypePointer t = type ( _operation . subExpression ( ) ) - > unaryOperatorResult ( op ) ;
if ( ! t )
{
2020-04-28 15:15:55 +00:00
string description = " Unary operator " + string ( TokenTraits : : toString ( op ) ) + " cannot be applied to type " + subExprType - > toString ( ) ;
if ( modifying )
// Cannot just report the error, ignore the unary operator, and continue,
// because the sub-expression was already processed with requireLValue()
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 9767 _error , _operation . location ( ) , description ) ;
2020-04-28 15:15:55 +00:00
else
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4907 _error , _operation . location ( ) , description ) ;
2015-09-16 14:56:30 +00:00
t = subExprType ;
}
_operation . annotation ( ) . type = t ;
2020-09-10 10:01:23 +00:00
_operation . annotation ( ) . isConstant = false ;
_operation . annotation ( ) . isPure = ! modifying & & * _operation . subExpression ( ) . annotation ( ) . isPure ;
_operation . annotation ( ) . isLValue = false ;
2020-10-05 10:21:30 +00:00
2015-09-16 14:56:30 +00:00
return false ;
}
void TypeChecker : : endVisit ( BinaryOperation const & _operation )
{
TypePointer const & leftType = type ( _operation . leftExpression ( ) ) ;
TypePointer const & rightType = type ( _operation . rightExpression ( ) ) ;
2018-12-05 13:34:27 +00:00
TypeResult result = leftType - > binaryOperatorResult ( _operation . getOperator ( ) , rightType ) ;
TypePointer commonType = result . get ( ) ;
2015-09-16 14:56:30 +00:00
if ( ! commonType )
{
2017-05-11 13:26:35 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
2271 _error ,
2015-11-04 10:49:26 +00:00
_operation . location ( ) ,
2015-09-16 14:56:30 +00:00
" Operator " +
2018-10-22 14:48:21 +00:00
string ( TokenTraits : : toString ( _operation . getOperator ( ) ) ) +
2015-09-16 14:56:30 +00:00
" not compatible with types " +
leftType - > toString ( ) +
" and " +
2018-12-05 13:34:27 +00:00
rightType - > toString ( ) +
( ! result . message ( ) . empty ( ) ? " . " + result . message ( ) : " " )
2015-09-16 14:56:30 +00:00
) ;
commonType = leftType ;
}
_operation . annotation ( ) . commonType = commonType ;
_operation . annotation ( ) . type =
2018-10-22 14:48:21 +00:00
TokenTraits : : isCompareOp ( _operation . getOperator ( ) ) ?
2019-04-17 11:40:50 +00:00
TypeProvider : : boolean ( ) :
2015-09-16 14:56:30 +00:00
commonType ;
2017-03-01 18:12:40 +00:00
_operation . annotation ( ) . isPure =
2020-09-10 10:01:23 +00:00
* _operation . leftExpression ( ) . annotation ( ) . isPure & &
* _operation . rightExpression ( ) . annotation ( ) . isPure ;
_operation . annotation ( ) . isLValue = false ;
_operation . annotation ( ) . isConstant = false ;
2017-03-01 18:12:40 +00:00
2017-08-16 11:52:06 +00:00
if ( _operation . getOperator ( ) = = Token : : Exp | | _operation . getOperator ( ) = = Token : : SHL )
2017-03-07 12:44:11 +00:00
{
2017-08-16 11:52:06 +00:00
string operation = _operation . getOperator ( ) = = Token : : Exp ? " exponentiation " : " shift " ;
2017-03-07 12:44:11 +00:00
if (
leftType - > category ( ) = = Type : : Category : : RationalNumber & &
rightType - > category ( ) ! = Type : : Category : : RationalNumber
)
if ( (
commonType - > category ( ) = = Type : : Category : : Integer & &
dynamic_cast < IntegerType const & > ( * commonType ) . numBits ( ) ! = 256
) | | (
commonType - > category ( ) = = Type : : Category : : FixedPoint & &
dynamic_cast < FixedPointType const & > ( * commonType ) . numBits ( ) ! = 256
) )
2017-05-11 13:26:35 +00:00
m_errorReporter . warning (
2020-05-05 22:38:28 +00:00
9085 _error ,
2017-03-07 12:44:11 +00:00
_operation . location ( ) ,
2017-08-16 11:52:06 +00:00
" Result of " + operation + " has type " + commonType - > toString ( ) + " and thus "
2017-03-07 12:44:11 +00:00
" might overflow. Silence this warning by converting the literal to the "
" expected type. "
) ;
2019-07-07 15:53:03 +00:00
if (
commonType - > category ( ) = = Type : : Category : : Integer & &
rightType - > category ( ) = = Type : : Category : : Integer & &
dynamic_cast < IntegerType const & > ( * commonType ) . numBits ( ) <
dynamic_cast < IntegerType const & > ( * rightType ) . numBits ( )
)
m_errorReporter . warning (
2020-05-05 22:38:28 +00:00
3149 _error ,
2019-07-07 15:53:03 +00:00
_operation . location ( ) ,
" The result type of the " +
operation +
" operation is equal to the type of the first operand ( " +
commonType - > toString ( ) +
" ) ignoring the (larger) type of the second operand ( " +
rightType - > toString ( ) +
" ) which might be unexpected. Silence this warning by either converting "
" the first or the second operand to the type of the other. "
) ;
2017-03-07 12:44:11 +00:00
}
2015-09-16 14:56:30 +00:00
}
2018-10-18 21:53:59 +00:00
TypePointer TypeChecker : : typeCheckTypeConversionAndRetrieveReturnType (
FunctionCall const & _functionCall
)
2015-09-16 14:56:30 +00:00
{
2020-04-08 17:38:30 +00:00
solAssert ( * _functionCall . annotation ( ) . kind = = FunctionCallKind : : TypeConversion , " " ) ;
2018-10-18 21:53:59 +00:00
TypePointer const & expressionType = type ( _functionCall . expression ( ) ) ;
2015-09-16 14:56:30 +00:00
2018-10-18 21:53:59 +00:00
vector < ASTPointer < Expression const > > const & arguments = _functionCall . arguments ( ) ;
bool const isPositionalCall = _functionCall . names ( ) . empty ( ) ;
2017-05-19 13:45:01 +00:00
2018-10-18 21:53:59 +00:00
TypePointer resultType = dynamic_cast < TypeType const & > ( * expressionType ) . actualType ( ) ;
if ( arguments . size ( ) ! = 1 )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
2558 _error ,
2018-10-18 21:53:59 +00:00
_functionCall . location ( ) ,
" Exactly one argument expected for explicit type conversion. "
) ;
else if ( ! isPositionalCall )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
5153 _error ,
2018-10-18 21:53:59 +00:00
_functionCall . location ( ) ,
" Type conversion cannot allow named arguments. "
) ;
2015-09-16 14:56:30 +00:00
else
{
2019-04-15 13:33:39 +00:00
Type const * argType = type ( * arguments . front ( ) ) ;
2018-10-18 21:53:59 +00:00
// Resulting data location is memory unless we are converting from a reference
// type with a different data location.
// (data location cannot yet be specified for type conversions)
DataLocation dataLoc = DataLocation : : Memory ;
2019-04-15 13:33:39 +00:00
if ( auto argRefType = dynamic_cast < ReferenceType const * > ( argType ) )
2018-10-18 21:53:59 +00:00
dataLoc = argRefType - > location ( ) ;
2019-04-15 13:33:39 +00:00
if ( auto type = dynamic_cast < ReferenceType const * > ( resultType ) )
resultType = TypeProvider : : withLocation ( type , dataLoc , type - > isPointer ( ) ) ;
2020-09-23 14:08:55 +00:00
BoolResult result = argType - > isExplicitlyConvertibleTo ( * resultType ) ;
if ( result )
2015-09-16 14:56:30 +00:00
{
2019-04-15 13:33:39 +00:00
if ( auto argArrayType = dynamic_cast < ArrayType const * > ( argType ) )
2018-09-12 10:01:34 +00:00
{
2019-04-15 13:33:39 +00:00
auto resultArrayType = dynamic_cast < ArrayType const * > ( resultType ) ;
2018-10-18 21:53:59 +00:00
solAssert ( ! ! resultArrayType , " " ) ;
solAssert (
argArrayType - > location ( ) ! = DataLocation : : Storage | |
(
(
resultArrayType - > isPointer ( ) | |
( argArrayType - > isByteArray ( ) & & resultArrayType - > isByteArray ( ) )
) & &
resultArrayType - > location ( ) = = DataLocation : : Storage
) ,
" Invalid explicit conversion to storage type. "
) ;
2018-09-05 15:59:55 +00:00
}
2018-10-18 21:53:59 +00:00
}
else
{
if (
resultType - > category ( ) = = Type : : Category : : Contract & &
argType - > category ( ) = = Type : : Category : : Address
)
2018-09-05 15:59:55 +00:00
{
2019-04-15 13:33:39 +00:00
solAssert ( dynamic_cast < ContractType const * > ( resultType ) - > isPayable ( ) , " " ) ;
2018-10-18 21:53:59 +00:00
solAssert (
2019-04-15 13:33:39 +00:00
dynamic_cast < AddressType const * > ( argType ) - > stateMutability ( ) <
2018-10-18 21:53:59 +00:00
StateMutability : : Payable ,
" "
) ;
SecondarySourceLocation ssl ;
if (
auto const * identifier = dynamic_cast < Identifier const * > ( arguments . front ( ) . get ( ) )
)
if (
auto const * variableDeclaration = dynamic_cast < VariableDeclaration const * > (
identifier - > annotation ( ) . referencedDeclaration
)
)
ssl . append (
" Did you mean to declare this variable as \" address payable \" ? " ,
variableDeclaration - > location ( )
) ;
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
7398 _error ,
2019-08-15 16:46:44 +00:00
_functionCall . location ( ) ,
ssl ,
2018-10-18 21:53:59 +00:00
" Explicit type conversion not allowed from non-payable \" address \" to \" " +
resultType - > toString ( ) +
" \" , which has a payable fallback function. "
) ;
2018-09-05 15:59:55 +00:00
}
2019-08-15 16:46:44 +00:00
else if (
auto const * functionType = dynamic_cast < FunctionType const * > ( argType ) ;
functionType & &
functionType - > kind ( ) = = FunctionType : : Kind : : External & &
resultType - > category ( ) = = Type : : Category : : Address
)
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
5030 _error ,
2019-08-15 16:46:44 +00:00
_functionCall . location ( ) ,
" Explicit type conversion not allowed from \" " +
argType - > toString ( ) +
" \" to \" " +
resultType - > toString ( ) +
" \" . To obtain the address of the contract of the function, " +
" you can use the .address member of the function. "
) ;
2018-10-18 21:53:59 +00:00
else
2020-09-23 14:08:55 +00:00
m_errorReporter . typeErrorConcatenateDescriptions (
2020-05-05 22:38:28 +00:00
9640 _error ,
2018-10-18 21:53:59 +00:00
_functionCall . location ( ) ,
" Explicit type conversion not allowed from \" " +
argType - > toString ( ) +
" \" to \" " +
resultType - > toString ( ) +
2020-09-23 14:08:55 +00:00
" \" . " ,
result . message ( )
2018-10-18 21:53:59 +00:00
) ;
}
2019-09-04 15:45:12 +00:00
if ( auto addressType = dynamic_cast < AddressType const * > ( resultType ) )
if ( addressType - > stateMutability ( ) ! = StateMutability : : Payable )
{
bool payable = false ;
if ( argType - > category ( ) ! = Type : : Category : : Address )
payable = argType - > isExplicitlyConvertibleTo ( * TypeProvider : : payableAddress ( ) ) ;
resultType = payable ? TypeProvider : : payableAddress ( ) : TypeProvider : : address ( ) ;
}
2015-09-16 14:56:30 +00:00
}
2018-10-18 21:53:59 +00:00
return resultType ;
}
2015-09-16 14:56:30 +00:00
2018-10-18 21:53:59 +00:00
void TypeChecker : : typeCheckFunctionCall (
FunctionCall const & _functionCall ,
FunctionTypePointer _functionType
)
{
2015-09-16 14:56:30 +00:00
// Actual function call or struct constructor call.
2018-10-18 21:53:59 +00:00
solAssert ( ! ! _functionType , " " ) ;
solAssert ( _functionType - > kind ( ) ! = FunctionType : : Kind : : ABIDecode , " " ) ;
2015-09-16 14:56:30 +00:00
2020-01-07 10:42:37 +00:00
if ( _functionType - > kind ( ) = = FunctionType : : Kind : : Declaration )
{
2020-05-04 16:38:00 +00:00
solAssert ( _functionType - > declaration ( ) . annotation ( ) . contract , " " ) ;
2020-03-06 09:44:51 +00:00
if (
2020-05-04 16:38:00 +00:00
m_currentContract & &
2020-06-09 16:17:58 +00:00
m_currentContract - > derivesFrom ( * _functionType - > declaration ( ) . annotation ( ) . contract ) & &
2020-03-06 09:44:51 +00:00
! dynamic_cast < FunctionDefinition const & > ( _functionType - > declaration ( ) ) . isImplemented ( )
)
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
7501 _error ,
2020-03-06 09:44:51 +00:00
_functionCall . location ( ) ,
" Cannot call unimplemented base function. "
) ;
else
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
3419 _error ,
2020-03-06 09:44:51 +00:00
_functionCall . location ( ) ,
" Cannot call function via contract type name. "
) ;
2020-01-07 10:42:37 +00:00
return ;
}
2018-10-18 21:53:59 +00:00
// Check for unsupported use of bare static call
if (
_functionType - > kind ( ) = = FunctionType : : Kind : : BareStaticCall & &
! m_evmVersion . hasStaticCall ( )
)
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
5052 _error ,
2018-10-18 21:53:59 +00:00
_functionCall . location ( ) ,
" \" staticcall \" is not supported by the VM version. "
) ;
// Perform standard function call type checking
typeCheckFunctionGeneralChecks ( _functionCall , _functionType ) ;
}
2019-09-09 16:22:02 +00:00
void TypeChecker : : typeCheckFallbackFunction ( FunctionDefinition const & _function )
{
solAssert ( _function . isFallback ( ) , " " ) ;
2020-06-09 15:56:58 +00:00
if ( _function . libraryFunction ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 5982 _error , _function . location ( ) , " Libraries cannot have fallback functions. " ) ;
2019-09-09 16:22:02 +00:00
if ( _function . stateMutability ( ) ! = StateMutability : : NonPayable & & _function . stateMutability ( ) ! = StateMutability : : Payable )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
4575 _error ,
2019-09-09 16:22:02 +00:00
_function . location ( ) ,
" Fallback function must be payable or non-payable, but is \" " +
stateMutabilityToString ( _function . stateMutability ( ) ) +
" \" . "
) ;
2019-12-10 14:54:09 +00:00
if ( _function . visibility ( ) ! = Visibility : : External )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 1159 _error , _function . location ( ) , " Fallback function must be defined as \" external \" . " ) ;
2019-09-09 16:22:02 +00:00
if ( ! _function . returnParameters ( ) . empty ( ) )
{
if ( _function . returnParameters ( ) . size ( ) > 1 | | * type ( * _function . returnParameters ( ) . front ( ) ) ! = * TypeProvider : : bytesMemory ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 5570 _error , _function . returnParameterList ( ) - > location ( ) , " Fallback function can only have a single \" bytes memory \" return value. " ) ;
2019-09-09 16:22:02 +00:00
else
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6151 _error , _function . returnParameterList ( ) - > location ( ) , " Return values for fallback functions are not yet implemented. " ) ;
2019-09-09 16:22:02 +00:00
}
if ( ! _function . parameters ( ) . empty ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 3978 _error , _function . parameterList ( ) . location ( ) , " Fallback function cannot take parameters. " ) ;
2019-09-09 16:22:02 +00:00
}
void TypeChecker : : typeCheckReceiveFunction ( FunctionDefinition const & _function )
{
solAssert ( _function . isReceive ( ) , " " ) ;
2020-06-09 15:56:58 +00:00
if ( _function . libraryFunction ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4549 _error , _function . location ( ) , " Libraries cannot have receive ether functions. " ) ;
2019-09-09 16:22:02 +00:00
if ( _function . stateMutability ( ) ! = StateMutability : : Payable )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
7793 _error ,
2019-09-09 16:22:02 +00:00
_function . location ( ) ,
" Receive ether function must be payable, but is \" " +
stateMutabilityToString ( _function . stateMutability ( ) ) +
" \" . "
) ;
2019-12-10 14:54:09 +00:00
if ( _function . visibility ( ) ! = Visibility : : External )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4095 _error , _function . location ( ) , " Receive ether function must be defined as \" external \" . " ) ;
2019-09-09 16:22:02 +00:00
if ( ! _function . returnParameters ( ) . empty ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6899 _error , _function . returnParameterList ( ) - > location ( ) , " Receive ether function cannot return values. " ) ;
2019-09-09 16:22:02 +00:00
if ( ! _function . parameters ( ) . empty ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 6857 _error , _function . parameterList ( ) . location ( ) , " Receive ether function cannot take parameters. " ) ;
2019-09-09 16:22:02 +00:00
}
void TypeChecker : : typeCheckConstructor ( FunctionDefinition const & _function )
{
solAssert ( _function . isConstructor ( ) , " " ) ;
2020-04-15 11:58:37 +00:00
if ( _function . overrides ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 1209 _error , _function . location ( ) , " Constructors cannot override. " ) ;
2019-09-09 16:22:02 +00:00
if ( ! _function . returnParameters ( ) . empty ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 9712 _error , _function . returnParameterList ( ) - > location ( ) , " Non-empty \" returns \" directive for constructor. " ) ;
2019-09-09 16:22:02 +00:00
if ( _function . stateMutability ( ) ! = StateMutability : : NonPayable & & _function . stateMutability ( ) ! = StateMutability : : Payable )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
1558 _error ,
2019-09-09 16:22:02 +00:00
_function . location ( ) ,
" Constructor must be payable or non-payable, but is \" " +
stateMutabilityToString ( _function . stateMutability ( ) ) +
" \" . "
) ;
2020-06-30 10:04:58 +00:00
if ( ! _function . noVisibilitySpecified ( ) )
{
auto const & contract = dynamic_cast < ContractDefinition const & > ( * _function . scope ( ) ) ;
if ( _function . visibility ( ) ! = Visibility : : Public & & _function . visibility ( ) ! = Visibility : : Internal )
m_errorReporter . typeError ( 9239 _error , _function . location ( ) , " Constructor cannot have visibility. " ) ;
else if ( _function . isPublic ( ) & & contract . abstract ( ) )
m_errorReporter . declarationError (
8295 _error ,
_function . location ( ) ,
" Abstract contracts cannot have public constructors. Remove the \" public \" keyword to fix this. "
) ;
else if ( ! _function . isPublic ( ) & & ! contract . abstract ( ) )
m_errorReporter . declarationError (
1845 _error ,
_function . location ( ) ,
" Non-abstract contracts cannot have internal constructors. Remove the \" internal \" keyword and make the contract abstract to fix this. "
) ;
else
m_errorReporter . warning (
2462 _error ,
_function . location ( ) ,
" Visibility for constructor is ignored. If you want the contract to be non-deployable, making it \" abstract \" is sufficient. "
) ;
}
2019-09-09 16:22:02 +00:00
}
2018-10-18 21:53:59 +00:00
void TypeChecker : : typeCheckABIEncodeFunctions (
FunctionCall const & _functionCall ,
FunctionTypePointer _functionType
)
{
solAssert ( ! ! _functionType , " " ) ;
solAssert (
_functionType - > kind ( ) = = FunctionType : : Kind : : ABIEncode | |
_functionType - > kind ( ) = = FunctionType : : Kind : : ABIEncodePacked | |
_functionType - > kind ( ) = = FunctionType : : Kind : : ABIEncodeWithSelector | |
_functionType - > kind ( ) = = FunctionType : : Kind : : ABIEncodeWithSignature ,
" ABI function has unexpected FunctionType::Kind. "
) ;
solAssert ( _functionType - > takesArbitraryParameters ( ) , " ABI functions should be variadic. " ) ;
bool const isPacked = _functionType - > kind ( ) = = FunctionType : : Kind : : ABIEncodePacked ;
solAssert ( _functionType - > padArguments ( ) ! = isPacked , " ABI function with unexpected padding " ) ;
2018-08-15 12:40:20 +00:00
2020-10-22 17:19:14 +00:00
bool const abiEncoderV2 = useABICoderV2 ( ) ;
2018-10-18 21:53:59 +00:00
// Check for named arguments
if ( ! _functionCall . names ( ) . empty ( ) )
2017-07-31 19:31:12 +00:00
{
2018-10-18 21:53:59 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
2627 _error ,
2018-10-18 21:53:59 +00:00
_functionCall . location ( ) ,
" Named arguments cannot be used for functions that take arbitrary parameters. "
) ;
return ;
2017-07-31 19:31:12 +00:00
}
2018-10-18 21:53:59 +00:00
// Perform standard function call type checking
typeCheckFunctionGeneralChecks ( _functionCall , _functionType ) ;
2017-08-25 11:17:44 +00:00
2018-10-18 21:53:59 +00:00
// Check additional arguments for variadic functions
vector < ASTPointer < Expression const > > const & arguments = _functionCall . arguments ( ) ;
for ( size_t i = 0 ; i < arguments . size ( ) ; + + i )
2017-08-25 11:17:44 +00:00
{
2018-10-18 21:53:59 +00:00
auto const & argType = type ( * arguments [ i ] ) ;
if ( argType - > category ( ) = = Type : : Category : : RationalNumber )
2017-08-25 11:17:44 +00:00
{
2019-01-17 12:36:06 +00:00
auto const & rationalType = dynamic_cast < RationalNumberType const & > ( * argType ) ;
if ( rationalType . isFractional ( ) )
{
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
6090 _error ,
2019-01-17 12:36:06 +00:00
arguments [ i ] - > location ( ) ,
2019-01-17 12:54:31 +00:00
" Fractional numbers cannot yet be encoded. "
2019-01-17 12:36:06 +00:00
) ;
continue ;
}
else if ( ! argType - > mobileType ( ) )
2017-08-25 11:17:44 +00:00
{
2018-10-18 21:53:59 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
8009 _error ,
2018-10-18 21:53:59 +00:00
arguments [ i ] - > location ( ) ,
" Invalid rational number (too large or division by zero). "
) ;
continue ;
}
else if ( isPacked )
{
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
7279 _error ,
2018-10-18 21:53:59 +00:00
arguments [ i ] - > location ( ) ,
" Cannot perform packed encoding for a literal. "
" Please convert it to an explicit type first. "
) ;
continue ;
2017-08-25 11:17:44 +00:00
}
}
2018-10-18 21:53:59 +00:00
2019-02-04 17:13:41 +00:00
if ( isPacked & & ! typeSupportedByOldABIEncoder ( * argType , false /* isLibrary */ ) )
{
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
9578 _error ,
2019-02-04 17:13:41 +00:00
arguments [ i ] - > location ( ) ,
" Type not supported in packed mode. "
) ;
continue ;
}
2018-10-18 21:53:59 +00:00
if ( ! argType - > fullEncodingType ( false , abiEncoderV2 , ! _functionType - > padArguments ( ) ) )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
2056 _error ,
2018-10-18 21:53:59 +00:00
arguments [ i ] - > location ( ) ,
" This type cannot be encoded. "
) ;
2017-08-25 11:17:44 +00:00
}
2018-10-18 21:53:59 +00:00
}
2017-08-25 11:17:44 +00:00
2018-10-18 21:53:59 +00:00
void TypeChecker : : typeCheckFunctionGeneralChecks (
FunctionCall const & _functionCall ,
FunctionTypePointer _functionType
)
{
// Actual function call or struct constructor call.
2018-06-30 16:09:13 +00:00
2018-10-18 21:53:59 +00:00
solAssert ( ! ! _functionType , " " ) ;
solAssert ( _functionType - > kind ( ) ! = FunctionType : : Kind : : ABIDecode , " " ) ;
2018-09-04 14:24:21 +00:00
2018-10-18 21:53:59 +00:00
bool const isPositionalCall = _functionCall . names ( ) . empty ( ) ;
bool const isVariadic = _functionType - > takesArbitraryParameters ( ) ;
2020-04-08 17:38:30 +00:00
auto functionCallKind = * _functionCall . annotation ( ) . kind ;
2018-10-18 21:53:59 +00:00
solAssert (
2020-04-08 17:38:30 +00:00
! isVariadic | | functionCallKind = = FunctionCallKind : : FunctionCall ,
2018-10-18 21:53:59 +00:00
" Struct constructor calls cannot be variadic. "
) ;
TypePointers const & parameterTypes = _functionType - > parameterTypes ( ) ;
vector < ASTPointer < Expression const > > const & arguments = _functionCall . arguments ( ) ;
vector < ASTPointer < ASTString > > const & argumentNames = _functionCall . names ( ) ;
// Check number of passed in arguments
if (
arguments . size ( ) < parameterTypes . size ( ) | |
( ! isVariadic & & arguments . size ( ) > parameterTypes . size ( ) )
)
2015-09-16 14:56:30 +00:00
{
2018-10-18 21:53:59 +00:00
bool const isStructConstructorCall =
2020-04-08 17:38:30 +00:00
functionCallKind = = FunctionCallKind : : StructConstructorCall ;
2018-10-18 21:53:59 +00:00
2020-05-21 01:49:31 +00:00
auto [ errorId , description ] = [ & ] ( ) - > tuple < ErrorId , string > {
string msg = isVariadic ?
2018-10-18 21:53:59 +00:00
" Need at least " +
toString ( parameterTypes . size ( ) ) +
" arguments for " +
string ( isStructConstructorCall ? " struct constructor " : " function call " ) +
" , but provided only " +
toString ( arguments . size ( ) ) +
2020-05-21 01:49:31 +00:00
" . "
:
2018-10-18 21:53:59 +00:00
" Wrong argument count for " +
string ( isStructConstructorCall ? " struct constructor " : " function call " ) +
" : " +
toString ( arguments . size ( ) ) +
" arguments given but " +
string ( isVariadic ? " need at least " : " expected " ) +
toString ( parameterTypes . size ( ) ) +
" . " ;
2018-01-04 10:24:39 +00:00
2020-05-21 01:49:31 +00:00
if ( isStructConstructorCall )
return { isVariadic ? 1123 _error : 9755 _error , msg } ;
else if (
_functionType - > kind ( ) = = FunctionType : : Kind : : BareCall | |
_functionType - > kind ( ) = = FunctionType : : Kind : : BareCallCode | |
_functionType - > kind ( ) = = FunctionType : : Kind : : BareDelegateCall | |
_functionType - > kind ( ) = = FunctionType : : Kind : : BareStaticCall
)
2018-10-18 21:53:59 +00:00
{
2020-05-21 01:49:31 +00:00
if ( arguments . empty ( ) )
return {
isVariadic ? 7653 _error : 6138 _error ,
msg +
" This function requires a single bytes argument. "
" Use \" \" as argument to provide empty calldata. "
} ;
else
return {
isVariadic ? 9390 _error : 8922 _error ,
msg +
" This function requires a single bytes argument. "
" If all your arguments are value types, you can use "
" abi.encode(...) to properly generate it. "
} ;
2018-10-18 21:53:59 +00:00
}
2020-05-21 01:49:31 +00:00
else if (
_functionType - > kind ( ) = = FunctionType : : Kind : : KECCAK256 | |
_functionType - > kind ( ) = = FunctionType : : Kind : : SHA256 | |
_functionType - > kind ( ) = = FunctionType : : Kind : : RIPEMD160
)
return {
isVariadic ? 1220 _error : 4323 _error ,
msg +
2018-10-18 21:53:59 +00:00
" This function requires a single bytes argument. "
2020-05-21 01:49:31 +00:00
" Use abi.encodePacked(...) to obtain the pre-0.5.0 "
" behaviour or abi.encode(...) to use ABI encoding. "
} ;
2018-06-14 14:08:59 +00:00
else
2020-05-21 01:49:31 +00:00
return { isVariadic ? 9308 _error : 6160 _error , msg } ;
} ( ) ;
m_errorReporter . typeError ( errorId , _functionCall . location ( ) , description ) ;
2018-10-18 21:53:59 +00:00
return ;
2015-09-16 14:56:30 +00:00
}
2018-10-18 21:53:59 +00:00
// Parameter to argument map
std : : vector < Expression const * > paramArgMap ( parameterTypes . size ( ) ) ;
// Map parameters to arguments - trivially for positional calls, less so for named calls
if ( isPositionalCall )
for ( size_t i = 0 ; i < paramArgMap . size ( ) ; + + i )
paramArgMap [ i ] = arguments [ i ] . get ( ) ;
2015-09-16 14:56:30 +00:00
else
{
2018-10-18 21:53:59 +00:00
auto const & parameterNames = _functionType - > parameterNames ( ) ;
2019-02-07 14:53:11 +00:00
solAssert (
parameterNames . size ( ) = = argumentNames . size ( ) ,
" Unexpected parameter length mismatch! "
) ;
2018-10-18 21:53:59 +00:00
// Check for duplicate argument names
2015-09-16 14:56:30 +00:00
{
bool duplication = false ;
for ( size_t i = 0 ; i < argumentNames . size ( ) ; i + + )
for ( size_t j = i + 1 ; j < argumentNames . size ( ) ; j + + )
if ( * argumentNames [ i ] = = * argumentNames [ j ] )
{
duplication = true ;
2018-10-18 21:53:59 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
6995 _error ,
2018-10-18 21:53:59 +00:00
arguments [ i ] - > location ( ) ,
" Duplicate named argument \" " + * argumentNames [ i ] + " \" . "
) ;
2015-09-16 14:56:30 +00:00
}
2018-10-18 21:53:59 +00:00
if ( duplication )
return ;
}
2015-09-16 14:56:30 +00:00
2018-10-18 21:53:59 +00:00
// map parameter names to argument names
{
bool not_all_mapped = false ;
2020-09-17 15:21:47 +00:00
for ( size_t i = 0 ; i < argumentNames . size ( ) ; i + + )
2018-10-18 21:53:59 +00:00
{
size_t j ;
2020-09-17 15:21:47 +00:00
for ( j = 0 ; j < parameterNames . size ( ) ; j + + )
if ( parameterNames [ j ] = = * argumentNames [ i ] )
2018-10-18 21:53:59 +00:00
break ;
2020-09-17 15:21:47 +00:00
if ( j < parameterNames . size ( ) )
paramArgMap [ j ] = arguments [ i ] . get ( ) ;
2018-10-18 21:53:59 +00:00
else
2015-09-16 14:56:30 +00:00
{
2018-10-18 21:53:59 +00:00
not_all_mapped = true ;
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
4974 _error ,
2018-10-18 21:53:59 +00:00
_functionCall . location ( ) ,
" Named argument \" " +
* argumentNames [ i ] +
" \" does not match function declaration. "
) ;
2015-09-16 14:56:30 +00:00
}
2018-10-18 21:53:59 +00:00
}
if ( not_all_mapped )
return ;
2015-09-16 14:56:30 +00:00
}
}
2018-10-18 21:53:59 +00:00
// Check for compatible types between arguments and parameters
for ( size_t i = 0 ; i < paramArgMap . size ( ) ; + + i )
{
solAssert ( ! ! paramArgMap [ i ] , " unmapped parameter " ) ;
if ( ! type ( * paramArgMap [ i ] ) - > isImplicitlyConvertibleTo ( * parameterTypes [ i ] ) )
{
2020-05-21 01:49:31 +00:00
auto [ errorId , description ] = [ & ] ( ) - > tuple < ErrorId , string > {
string msg =
" Invalid type for argument in function call. "
" Invalid implicit conversion from " +
type ( * paramArgMap [ i ] ) - > toString ( ) +
" to " +
parameterTypes [ i ] - > toString ( ) +
" requested. " ;
if (
_functionType - > kind ( ) = = FunctionType : : Kind : : BareCall | |
_functionType - > kind ( ) = = FunctionType : : Kind : : BareCallCode | |
_functionType - > kind ( ) = = FunctionType : : Kind : : BareDelegateCall | |
_functionType - > kind ( ) = = FunctionType : : Kind : : BareStaticCall
)
return {
8051 _error ,
msg +
" This function requires a single bytes argument. "
" If all your arguments are value types, you can "
" use abi.encode(...) to properly generate it. "
} ;
else if (
_functionType - > kind ( ) = = FunctionType : : Kind : : KECCAK256 | |
_functionType - > kind ( ) = = FunctionType : : Kind : : SHA256 | |
_functionType - > kind ( ) = = FunctionType : : Kind : : RIPEMD160
)
return {
7556 _error ,
msg +
" This function requires a single bytes argument. "
" Use abi.encodePacked(...) to obtain the pre-0.5.0 "
" behaviour or abi.encode(...) to use ABI encoding. "
} ;
else
return { 9553 _error , msg } ;
} ( ) ;
m_errorReporter . typeError ( errorId , paramArgMap [ i ] - > location ( ) , description ) ;
2018-10-18 21:53:59 +00:00
}
}
2020-09-17 13:03:49 +00:00
TypePointers const & returnParameterTypes = _functionType - > returnParameterTypes ( ) ;
bool isLibraryCall = ( _functionType - > kind ( ) = = FunctionType : : Kind : : DelegateCall ) ;
bool callRequiresABIEncoding =
// ABIEncode/ABIDecode calls not included because they should have been already validated
// at this point and they have variadic arguments so they need special handling.
_functionType - > kind ( ) = = FunctionType : : Kind : : DelegateCall | |
_functionType - > kind ( ) = = FunctionType : : Kind : : External | |
_functionType - > kind ( ) = = FunctionType : : Kind : : Creation | |
_functionType - > kind ( ) = = FunctionType : : Kind : : Event ;
2020-10-22 17:19:14 +00:00
if ( callRequiresABIEncoding & & ! useABICoderV2 ( ) )
2020-09-17 13:03:49 +00:00
{
solAssert ( ! isVariadic , " " ) ;
solAssert ( parameterTypes . size ( ) = = arguments . size ( ) , " " ) ;
solAssert ( ! _functionType - > isBareCall ( ) , " " ) ;
solAssert ( * _functionCall . annotation ( ) . kind = = FunctionCallKind : : FunctionCall , " " ) ;
for ( size_t i = 0 ; i < parameterTypes . size ( ) ; + + i )
{
solAssert ( parameterTypes [ i ] , " " ) ;
if ( ! typeSupportedByOldABIEncoder ( * parameterTypes [ i ] , isLibraryCall ) )
m_errorReporter . typeError (
2443 _error ,
paramArgMap [ i ] - > location ( ) ,
" The type of this parameter, " + parameterTypes [ i ] - > toString ( true ) + " , "
2020-10-29 18:40:17 +00:00
" is only supported in ABI coder v2. "
" Use \" pragma abicoder v2; \" to enable the feature. "
2020-09-17 13:03:49 +00:00
) ;
}
for ( size_t i = 0 ; i < returnParameterTypes . size ( ) ; + + i )
{
solAssert ( returnParameterTypes [ i ] , " " ) ;
if ( ! typeSupportedByOldABIEncoder ( * returnParameterTypes [ i ] , isLibraryCall ) )
m_errorReporter . typeError (
2428 _error ,
_functionCall . location ( ) ,
" The type of return parameter " + toString ( i + 1 ) + " , " + returnParameterTypes [ i ] - > toString ( true ) + " , "
2020-10-29 18:40:17 +00:00
" is only supported in ABI coder v2. "
" Use \" pragma abicoder v2; \" to enable the feature. "
2020-09-17 13:03:49 +00:00
) ;
}
}
2018-10-18 21:53:59 +00:00
}
bool TypeChecker : : visit ( FunctionCall const & _functionCall )
{
vector < ASTPointer < Expression const > > const & arguments = _functionCall . arguments ( ) ;
bool argumentsArePure = true ;
// We need to check arguments' type first as they will be needed for overload resolution.
for ( ASTPointer < Expression const > const & argument : arguments )
{
argument - > accept ( * this ) ;
2020-09-10 10:01:23 +00:00
if ( ! * argument - > annotation ( ) . isPure )
2018-10-18 21:53:59 +00:00
argumentsArePure = false ;
}
2019-03-19 16:12:21 +00:00
// Store argument types - and names if given - for overload resolution
2018-10-18 21:53:59 +00:00
{
2019-03-19 16:12:21 +00:00
FuncCallArguments funcCallArgs ;
funcCallArgs . names = _functionCall . names ( ) ;
2018-10-18 21:53:59 +00:00
for ( ASTPointer < Expression const > const & argument : arguments )
2019-03-19 16:12:21 +00:00
funcCallArgs . types . push_back ( type ( * argument ) ) ;
_functionCall . expression ( ) . annotation ( ) . arguments = std : : move ( funcCallArgs ) ;
2018-10-18 21:53:59 +00:00
}
_functionCall . expression ( ) . accept ( * this ) ;
2019-04-15 13:33:39 +00:00
Type const * expressionType = type ( _functionCall . expression ( ) ) ;
2018-10-18 21:53:59 +00:00
// Determine function call kind and function type for this FunctionCall node
FunctionCallAnnotation & funcCallAnno = _functionCall . annotation ( ) ;
2019-04-15 13:33:39 +00:00
FunctionTypePointer functionType = nullptr ;
2020-09-10 10:01:23 +00:00
funcCallAnno . isConstant = false ;
bool isLValue = false ;
2018-10-18 21:53:59 +00:00
2019-09-13 22:54:51 +00:00
// Determine and assign function call kind, lvalue, purity and function type for this FunctionCall node
2018-10-18 21:53:59 +00:00
switch ( expressionType - > category ( ) )
{
case Type : : Category : : Function :
2019-04-15 13:33:39 +00:00
functionType = dynamic_cast < FunctionType const * > ( expressionType ) ;
2018-10-18 21:53:59 +00:00
funcCallAnno . kind = FunctionCallKind : : FunctionCall ;
// Purity for function calls also depends upon the callee and its FunctionType
funcCallAnno . isPure =
argumentsArePure & &
2020-09-10 10:01:23 +00:00
* _functionCall . expression ( ) . annotation ( ) . isPure & &
2018-10-18 21:53:59 +00:00
functionType & &
functionType - > isPure ( ) ;
2019-09-13 22:54:51 +00:00
if (
functionType - > kind ( ) = = FunctionType : : Kind : : ArrayPush | |
functionType - > kind ( ) = = FunctionType : : Kind : : ByteArrayPush
)
2020-09-10 10:01:23 +00:00
isLValue = functionType - > parameterTypes ( ) . empty ( ) ;
2019-09-13 22:54:51 +00:00
2018-10-18 21:53:59 +00:00
break ;
case Type : : Category : : TypeType :
{
// Determine type for type conversion or struct construction expressions
TypePointer const & actualType = dynamic_cast < TypeType const & > ( * expressionType ) . actualType ( ) ;
solAssert ( ! ! actualType , " " ) ;
if ( actualType - > category ( ) = = Type : : Category : : Struct )
{
2020-06-03 10:38:35 +00:00
if ( actualType - > containsNestedMapping ( ) )
m_errorReporter . fatalTypeError (
9515 _error ,
_functionCall . location ( ) ,
" Struct containing a (nested) mapping cannot be constructed. "
) ;
2018-10-18 21:53:59 +00:00
functionType = dynamic_cast < StructType const & > ( * actualType ) . constructorType ( ) ;
funcCallAnno . kind = FunctionCallKind : : StructConstructorCall ;
}
else
funcCallAnno . kind = FunctionCallKind : : TypeConversion ;
2020-09-10 10:01:23 +00:00
funcCallAnno . isPure = argumentsArePure ;
2018-10-18 21:53:59 +00:00
break ;
}
default :
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 5704 _error , _functionCall . location ( ) , " Type is not callable " ) ;
2020-04-08 17:38:30 +00:00
// Unreachable, because fatalTypeError throws. We don't set kind, but that's okay because the switch below
// is never reached. And, even if it was, SetOnce would trigger an assertion violation and not UB.
2018-10-18 21:53:59 +00:00
funcCallAnno . isPure = argumentsArePure ;
break ;
}
2020-09-10 10:01:23 +00:00
funcCallAnno . isLValue = isLValue ;
2018-10-18 21:53:59 +00:00
// Determine return types
2020-04-08 17:38:30 +00:00
switch ( * funcCallAnno . kind )
2018-10-18 21:53:59 +00:00
{
case FunctionCallKind : : TypeConversion :
funcCallAnno . type = typeCheckTypeConversionAndRetrieveReturnType ( _functionCall ) ;
break ;
case FunctionCallKind : : StructConstructorCall : // fall-through
case FunctionCallKind : : FunctionCall :
{
TypePointers returnTypes ;
switch ( functionType - > kind ( ) )
{
case FunctionType : : Kind : : ABIDecode :
{
2020-06-11 22:16:24 +00:00
returnTypes = typeCheckABIDecodeAndRetrieveReturnType (
_functionCall ,
2020-10-22 17:19:14 +00:00
useABICoderV2 ( )
2020-06-11 22:16:24 +00:00
) ;
2018-10-18 21:53:59 +00:00
break ;
}
case FunctionType : : Kind : : ABIEncode :
case FunctionType : : Kind : : ABIEncodePacked :
case FunctionType : : Kind : : ABIEncodeWithSelector :
case FunctionType : : Kind : : ABIEncodeWithSignature :
{
typeCheckABIEncodeFunctions ( _functionCall , functionType ) ;
returnTypes = functionType - > returnParameterTypes ( ) ;
break ;
}
2019-01-10 15:28:39 +00:00
case FunctionType : : Kind : : MetaType :
returnTypes = typeCheckMetaTypeFunctionAndRetrieveReturnType ( _functionCall ) ;
break ;
2018-10-18 21:53:59 +00:00
default :
{
typeCheckFunctionCall ( _functionCall , functionType ) ;
returnTypes = m_evmVersion . supportsReturndata ( ) ?
functionType - > returnParameterTypes ( ) :
functionType - > returnParameterTypesWithoutDynamicTypes ( ) ;
break ;
}
}
funcCallAnno . type = returnTypes . size ( ) = = 1 ?
move ( returnTypes . front ( ) ) :
2019-04-17 11:40:50 +00:00
TypeProvider : : tuple ( move ( returnTypes ) ) ;
2018-10-18 21:53:59 +00:00
break ;
}
default :
// for non-callables, ensure error reported and annotate node to void function
solAssert ( m_errorReporter . hasErrors ( ) , " " ) ;
funcCallAnno . kind = FunctionCallKind : : FunctionCall ;
2019-04-17 11:40:50 +00:00
funcCallAnno . type = TypeProvider : : emptyTuple ( ) ;
2018-10-18 21:53:59 +00:00
break ;
}
2018-09-04 14:24:21 +00:00
2015-09-16 14:56:30 +00:00
return false ;
}
2020-01-22 14:42:50 +00:00
bool TypeChecker : : visit ( FunctionCallOptions const & _functionCallOptions )
{
solAssert ( _functionCallOptions . options ( ) . size ( ) = = _functionCallOptions . names ( ) . size ( ) , " Lengths of name & value arrays differ! " ) ;
2020-07-07 09:30:15 +00:00
_functionCallOptions . expression ( ) . annotation ( ) . arguments = _functionCallOptions . annotation ( ) . arguments ;
2020-01-22 14:42:50 +00:00
_functionCallOptions . expression ( ) . accept ( * this ) ;
2020-09-10 10:01:23 +00:00
_functionCallOptions . annotation ( ) . isPure = false ;
_functionCallOptions . annotation ( ) . isConstant = false ;
2020-10-05 10:21:30 +00:00
_functionCallOptions . annotation ( ) . isLValue = false ;
2020-09-10 10:01:23 +00:00
2020-01-22 14:42:50 +00:00
auto expressionFunctionType = dynamic_cast < FunctionType const * > ( type ( _functionCallOptions . expression ( ) ) ) ;
if ( ! expressionFunctionType )
{
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 2622 _error , _functionCallOptions . location ( ) , " Expected callable expression before call options. " ) ;
2020-01-22 14:42:50 +00:00
return false ;
}
bool setSalt = false ;
bool setValue = false ;
bool setGas = false ;
FunctionType : : Kind kind = expressionFunctionType - > kind ( ) ;
if (
kind ! = FunctionType : : Kind : : Creation & &
kind ! = FunctionType : : Kind : : External & &
kind ! = FunctionType : : Kind : : BareCall & &
kind ! = FunctionType : : Kind : : BareCallCode & &
kind ! = FunctionType : : Kind : : BareDelegateCall & &
kind ! = FunctionType : : Kind : : BareStaticCall
)
{
m_errorReporter . fatalTypeError (
2020-05-05 22:38:28 +00:00
2193 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
" Function call options can only be set on external function calls or contract creations. "
) ;
return false ;
}
auto setCheckOption = [ & ] ( bool & _option , string const & & _name , bool _alreadySet = false )
{
if ( _option | | _alreadySet )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
9886 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
_alreadySet ?
" Option \" " + std : : move ( _name ) + " \" has already been set. " :
" Duplicate option \" " + std : : move ( _name ) + " \" . "
) ;
_option = true ;
} ;
for ( size_t i = 0 ; i < _functionCallOptions . names ( ) . size ( ) ; + + i )
{
string const & name = * ( _functionCallOptions . names ( ) [ i ] ) ;
if ( name = = " salt " )
{
if ( kind = = FunctionType : : Kind : : Creation )
{
setCheckOption ( setSalt , " salt " , expressionFunctionType - > saltSet ( ) ) ;
expectType ( * _functionCallOptions . options ( ) [ i ] , * TypeProvider : : fixedBytes ( 32 ) ) ;
}
else
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
2721 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
" Function call option \" salt \" can only be used with \" new \" . "
) ;
}
else if ( name = = " value " )
{
if ( kind = = FunctionType : : Kind : : BareDelegateCall )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
6189 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
" Cannot set option \" value \" for delegatecall. "
) ;
else if ( kind = = FunctionType : : Kind : : BareStaticCall )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
2842 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
" Cannot set option \" value \" for staticcall. "
) ;
else if ( ! expressionFunctionType - > isPayable ( ) )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
7006 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
2020-03-03 11:15:59 +00:00
kind = = FunctionType : : Kind : : Creation ?
" Cannot set option \" value \" , since the constructor of " +
expressionFunctionType - > returnParameterTypes ( ) . front ( ) - > toString ( ) +
" is not payable. " :
" Cannot set option \" value \" on a non-payable function type. "
2020-01-22 14:42:50 +00:00
) ;
else
{
expectType ( * _functionCallOptions . options ( ) [ i ] , * TypeProvider : : uint256 ( ) ) ;
setCheckOption ( setValue , " value " , expressionFunctionType - > valueSet ( ) ) ;
}
}
else if ( name = = " gas " )
{
if ( kind = = FunctionType : : Kind : : Creation )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
9903 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
" Function call option \" gas \" cannot be used with \" new \" . "
) ;
else
{
expectType ( * _functionCallOptions . options ( ) [ i ] , * TypeProvider : : uint256 ( ) ) ;
setCheckOption ( setGas , " gas " , expressionFunctionType - > gasSet ( ) ) ;
}
}
else
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
9318 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
" Unknown call option \" " + name + " \" . Valid options are \" salt \" , \" value \" and \" gas \" . "
) ;
}
if ( setSalt & & ! m_evmVersion . hasCreate2 ( ) )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
5189 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
" Unsupported call option \" salt \" (requires Constantinople-compatible VMs). "
) ;
_functionCallOptions . annotation ( ) . type = expressionFunctionType - > copyAndSetCallOptions ( setGas , setValue , setSalt ) ;
return false ;
}
2015-09-16 14:56:30 +00:00
void TypeChecker : : endVisit ( NewExpression const & _newExpression )
{
2015-11-17 00:47:47 +00:00
TypePointer type = _newExpression . typeName ( ) . annotation ( ) . type ;
solAssert ( ! ! type , " Type name not resolved. " ) ;
2020-09-10 10:01:23 +00:00
_newExpression . annotation ( ) . isConstant = false ;
2020-10-05 10:21:30 +00:00
_newExpression . annotation ( ) . isLValue = false ;
2020-09-10 10:01:23 +00:00
2015-11-16 23:06:57 +00:00
if ( auto contractName = dynamic_cast < UserDefinedTypeName const * > ( & _newExpression . typeName ( ) ) )
{
auto contract = dynamic_cast < ContractDefinition const * > ( & dereference ( * contractName ) ) ;
if ( ! contract )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 5540 _error , _newExpression . location ( ) , " Identifier is not a contract. " ) ;
2019-01-17 11:59:11 +00:00
if ( contract - > isInterface ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 2971 _error , _newExpression . location ( ) , " Cannot instantiate an interface. " ) ;
2019-11-04 13:12:58 +00:00
if ( contract - > abstract ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4614 _error , _newExpression . location ( ) , " Cannot instantiate an abstract contract. " ) ;
2015-11-16 23:06:57 +00:00
2020-05-04 16:38:00 +00:00
if ( m_currentContract )
{
// TODO this is not properly detecting creation-cycles if they go through
// internal library functions or free functions. It will be caught at
// code generation time, but it would of course be better to catch it here.
m_currentContract - > annotation ( ) . contractDependencies . insert ( contract ) ;
solAssert (
! contract - > annotation ( ) . linearizedBaseContracts . empty ( ) ,
" Linearized base contracts not yet available. "
2015-11-16 23:06:57 +00:00
) ;
2020-05-04 16:38:00 +00:00
if ( contractDependenciesAreCyclic ( * m_currentContract ) )
m_errorReporter . typeError (
4579 _error ,
_newExpression . location ( ) ,
" Circular reference for contract creation (cannot create instance of derived or same contract). "
) ;
}
2015-09-16 14:56:30 +00:00
2016-08-31 18:43:24 +00:00
_newExpression . annotation ( ) . type = FunctionType : : newExpressionType ( * contract ) ;
2020-09-10 10:01:23 +00:00
_newExpression . annotation ( ) . isPure = false ;
2015-11-16 23:06:57 +00:00
}
2015-11-17 00:47:47 +00:00
else if ( type - > category ( ) = = Type : : Category : : Array )
2015-11-16 23:06:57 +00:00
{
2020-06-03 10:38:35 +00:00
if ( type - > containsNestedMapping ( ) )
2017-05-11 13:26:35 +00:00
m_errorReporter . fatalTypeError (
2020-05-05 22:38:28 +00:00
1164 _error ,
2015-11-17 00:47:47 +00:00
_newExpression . typeName ( ) . location ( ) ,
2020-06-03 10:38:35 +00:00
" Array containing a (nested) mapping cannot be constructed in memory. "
2015-11-17 00:47:47 +00:00
) ;
if ( ! type - > isDynamicallySized ( ) )
2017-05-11 13:26:35 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
3904 _error ,
2015-11-17 00:47:47 +00:00
_newExpression . typeName ( ) . location ( ) ,
" Length has to be placed in parentheses after the array type for new expression. "
) ;
2019-04-17 11:25:03 +00:00
type = TypeProvider : : withLocationIfReference ( DataLocation : : Memory , type ) ;
2019-04-17 11:40:50 +00:00
_newExpression . annotation ( ) . type = TypeProvider : : function (
2019-04-15 16:10:43 +00:00
TypePointers { TypeProvider : : uint256 ( ) } ,
2015-11-17 00:47:47 +00:00
TypePointers { type } ,
2019-02-07 14:53:11 +00:00
strings ( 1 , " " ) ,
strings ( 1 , " " ) ,
2017-08-28 12:35:28 +00:00
FunctionType : : Kind : : ObjectCreation ,
false ,
StateMutability : : Pure
2015-11-17 00:47:47 +00:00
) ;
2017-03-01 18:12:40 +00:00
_newExpression . annotation ( ) . isPure = true ;
2015-11-16 23:06:57 +00:00
}
else
2020-10-05 10:21:30 +00:00
{
_newExpression . annotation ( ) . isPure = false ;
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 8807 _error , _newExpression . location ( ) , " Contract or array type expected. " ) ;
2020-10-05 10:21:30 +00:00
}
2015-09-16 14:56:30 +00:00
}
bool TypeChecker : : visit ( MemberAccess const & _memberAccess )
{
_memberAccess . expression ( ) . accept ( * this ) ;
TypePointer exprType = type ( _memberAccess . expression ( ) ) ;
ASTString const & memberName = _memberAccess . memberName ( ) ;
2020-09-16 09:00:07 +00:00
auto & annotation = _memberAccess . annotation ( ) ;
2015-09-16 14:56:30 +00:00
// Retrieve the types of the arguments if this is used to call a function.
2020-09-16 09:00:07 +00:00
auto const & arguments = annotation . arguments ;
2020-05-04 16:38:00 +00:00
MemberList : : MemberMap possibleMembers = exprType - > members ( currentDefinitionScope ( ) ) . membersByName ( memberName ) ;
2018-04-18 18:40:46 +00:00
size_t const initialMemberCount = possibleMembers . size ( ) ;
2019-03-19 16:12:21 +00:00
if ( initialMemberCount > 1 & & arguments )
2015-09-16 14:56:30 +00:00
{
// do overload resolution
for ( auto it = possibleMembers . begin ( ) ; it ! = possibleMembers . end ( ) ; )
if (
it - > type - > category ( ) = = Type : : Category : : Function & &
2019-03-19 16:12:21 +00:00
! dynamic_cast < FunctionType const & > ( * it - > type ) . canTakeArguments ( * arguments , exprType )
2015-09-16 14:56:30 +00:00
)
it = possibleMembers . erase ( it ) ;
else
+ + it ;
}
2018-07-17 12:31:21 +00:00
2020-09-10 10:01:23 +00:00
annotation . isConstant = false ;
2018-10-09 03:29:37 +00:00
if ( possibleMembers . empty ( ) )
2015-09-16 14:56:30 +00:00
{
2020-05-26 15:23:49 +00:00
if ( initialMemberCount = = 0 & & ! dynamic_cast < ArraySliceType const * > ( exprType ) )
2018-04-18 18:40:46 +00:00
{
// Try to see if the member was removed because it is only available for storage types.
2019-04-17 11:25:03 +00:00
auto storageType = TypeProvider : : withLocationIfReference (
2018-04-18 18:40:46 +00:00
DataLocation : : Storage ,
exprType
2015-09-16 14:56:30 +00:00
) ;
2020-05-04 16:38:00 +00:00
if ( ! storageType - > members ( currentDefinitionScope ( ) ) . membersByName ( memberName ) . empty ( ) )
2018-04-18 18:40:46 +00:00
m_errorReporter . fatalTypeError (
2020-05-05 22:38:28 +00:00
4994 _error ,
2018-04-18 18:40:46 +00:00
_memberAccess . location ( ) ,
" Member \" " + memberName + " \" is not available in " +
exprType - > toString ( ) +
" outside of storage. "
) ;
}
2019-02-12 15:09:16 +00:00
2020-05-21 01:49:31 +00:00
auto [ errorId , description ] = [ & ] ( ) - > tuple < ErrorId , string > {
string errorMsg = " Member \" " + memberName + " \" not found or not visible "
" after argument-dependent lookup in " + exprType - > toString ( ) + " . " ;
2019-02-12 15:09:16 +00:00
2020-05-21 01:49:31 +00:00
if ( auto const * funType = dynamic_cast < FunctionType const * > ( exprType ) )
2019-02-12 15:09:16 +00:00
{
2020-05-21 01:49:31 +00:00
TypePointers const & t = funType - > returnParameterTypes ( ) ;
if ( memberName = = " value " )
{
if ( funType - > kind ( ) = = FunctionType : : Kind : : Creation )
return {
8827 _error ,
" Constructor for " + t . front ( ) - > toString ( ) + " must be payable for member \" value \" to be available. "
} ;
else if (
funType - > kind ( ) = = FunctionType : : Kind : : DelegateCall | |
funType - > kind ( ) = = FunctionType : : Kind : : BareDelegateCall
)
return { 8477 _error , " Member \" value \" is not allowed in delegated calls due to \" msg.value \" persisting. " } ;
else
return { 8820 _error , " Member \" value \" is only available for payable functions. " } ;
}
2019-06-06 08:36:41 +00:00
else if (
2020-05-21 01:49:31 +00:00
t . size ( ) = = 1 & & (
t . front ( ) - > category ( ) = = Type : : Category : : Struct | |
t . front ( ) - > category ( ) = = Type : : Category : : Contract
)
2019-06-06 08:36:41 +00:00
)
2020-05-21 01:49:31 +00:00
return { 6005 _error , errorMsg + " Did you intend to call the function? " } ;
2019-02-12 15:09:16 +00:00
}
2020-05-21 01:49:31 +00:00
else if ( exprType - > category ( ) = = Type : : Category : : Contract )
2019-02-12 15:56:22 +00:00
{
2020-05-21 01:49:31 +00:00
for ( MemberList : : Member const & addressMember : TypeProvider : : payableAddress ( ) - > nativeMembers ( nullptr ) )
if ( addressMember . name = = memberName )
{
auto const * var = dynamic_cast < Identifier const * > ( & _memberAccess . expression ( ) ) ;
string varName = var ? var - > name ( ) : " ... " ;
errorMsg + = " Use \" address( " + varName + " ). " + memberName + " \" to access this address member. " ;
2020-05-26 12:37:31 +00:00
return { 3125 _error , errorMsg } ;
2020-05-21 01:49:31 +00:00
}
}
else if ( auto const * addressType = dynamic_cast < AddressType const * > ( exprType ) )
{
// Trigger error when using send or transfer with a non-payable fallback function.
if ( memberName = = " send " | | memberName = = " transfer " )
{
solAssert (
addressType - > stateMutability ( ) ! = StateMutability : : Payable ,
" Expected address not-payable as members were not found "
) ;
2019-02-12 15:56:22 +00:00
2020-05-26 12:37:31 +00:00
return { 9862 _error , " \" send \" and \" transfer \" are only available for objects of type \" address payable \" , not \" " + exprType - > toString ( ) + " \" . " } ;
2020-05-21 01:49:31 +00:00
}
2019-02-12 15:56:22 +00:00
}
2020-05-21 01:49:31 +00:00
2020-05-26 12:37:31 +00:00
return { 9582 _error , errorMsg } ;
2020-05-21 01:49:31 +00:00
} ( ) ;
2019-02-12 15:56:22 +00:00
2017-05-11 13:26:35 +00:00
m_errorReporter . fatalTypeError (
2020-05-21 01:49:31 +00:00
errorId ,
2015-11-04 10:49:26 +00:00
_memberAccess . location ( ) ,
2020-05-21 01:49:31 +00:00
description
2015-09-16 14:56:30 +00:00
) ;
}
else if ( possibleMembers . size ( ) > 1 )
2017-05-11 13:26:35 +00:00
m_errorReporter . fatalTypeError (
2020-05-05 22:38:28 +00:00
6675 _error ,
2015-11-04 10:49:26 +00:00
_memberAccess . location ( ) ,
2015-09-16 14:56:30 +00:00
" Member \" " + memberName + " \" not unique "
2016-08-26 18:37:10 +00:00
" after argument-dependent lookup in " + exprType - > toString ( ) +
2018-07-16 15:11:39 +00:00
( memberName = = " value " ? " - did you forget the \" payable \" modifier? " : " . " )
2015-09-16 14:56:30 +00:00
) ;
annotation . referencedDeclaration = possibleMembers . front ( ) . declaration ;
annotation . type = possibleMembers . front ( ) . type ;
2015-11-27 21:24:00 +00:00
2020-09-16 09:00:07 +00:00
VirtualLookup requiredLookup = VirtualLookup : : Static ;
2019-04-15 13:33:39 +00:00
if ( auto funType = dynamic_cast < FunctionType const * > ( annotation . type ) )
2020-03-03 11:15:59 +00:00
{
2019-02-12 10:41:05 +00:00
solAssert (
! funType - > bound ( ) | | exprType - > isImplicitlyConvertibleTo ( * funType - > selfType ( ) ) ,
" Function \" " + memberName + " \" cannot be called on an object of type " +
exprType - > toString ( ) + " (expected " + funType - > selfType ( ) - > toString ( ) + " ). "
) ;
2015-11-27 21:24:00 +00:00
2020-03-03 11:15:59 +00:00
if (
dynamic_cast < FunctionType const * > ( exprType ) & &
! annotation . referencedDeclaration & &
( memberName = = " value " | | memberName = = " gas " )
)
2020-04-03 11:43:33 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
1621 _error ,
2020-03-03 11:15:59 +00:00
_memberAccess . location ( ) ,
" Using \" . " + memberName + " (...) \" is deprecated. Use \" { " + memberName + " : ...} \" instead. "
) ;
2020-09-16 09:00:07 +00:00
2020-09-27 19:35:41 +00:00
if (
funType - > kind ( ) = = FunctionType : : Kind : : ArrayPush & &
arguments . value ( ) . numArguments ( ) ! = 0 & &
exprType - > containsNestedMapping ( )
)
m_errorReporter . typeError (
8871 _error ,
_memberAccess . location ( ) ,
" Storage arrays with nested mappings do not support .push(<arg>). "
) ;
2020-09-16 09:00:07 +00:00
if ( ! funType - > bound ( ) )
if ( auto contractType = dynamic_cast < ContractType const * > ( exprType ) )
2020-10-30 14:40:06 +00:00
if ( contractType - > isSuper ( ) )
requiredLookup = VirtualLookup : : Super ;
2020-03-03 11:15:59 +00:00
}
2020-09-16 09:00:07 +00:00
annotation . requiredLookup = requiredLookup ;
2019-04-15 13:33:39 +00:00
if ( auto const * structType = dynamic_cast < StructType const * > ( exprType ) )
2019-02-05 19:29:57 +00:00
annotation . isLValue = ! structType - > dataStoredIn ( DataLocation : : CallData ) ;
2015-09-16 14:56:30 +00:00
else if ( exprType - > category ( ) = = Type : : Category : : Array )
2019-09-18 12:58:20 +00:00
annotation . isLValue = false ;
2016-02-03 20:34:24 +00:00
else if ( exprType - > category ( ) = = Type : : Category : : FixedBytes )
annotation . isLValue = false ;
2019-04-15 13:33:39 +00:00
else if ( TypeType const * typeType = dynamic_cast < decltype ( typeType ) > ( exprType ) )
2016-10-24 17:22:09 +00:00
{
2019-04-15 13:33:39 +00:00
if ( ContractType const * contractType = dynamic_cast < decltype ( contractType ) > ( typeType - > actualType ( ) ) )
2020-02-07 11:44:52 +00:00
{
2016-10-24 17:22:09 +00:00
annotation . isLValue = annotation . referencedDeclaration - > isLValue ( ) ;
2020-02-07 11:44:52 +00:00
if (
auto const * functionType = dynamic_cast < FunctionType const * > ( annotation . type ) ;
functionType & &
functionType - > kind ( ) = = FunctionType : : Kind : : Declaration
)
2020-09-10 10:01:23 +00:00
annotation . isPure = * _memberAccess . expression ( ) . annotation ( ) . isPure ;
2020-02-07 11:44:52 +00:00
}
2020-10-05 10:21:30 +00:00
else
annotation . isLValue = false ;
2016-10-24 17:22:09 +00:00
}
2020-06-16 14:49:31 +00:00
else if ( exprType - > category ( ) = = Type : : Category : : Module )
2020-09-10 10:01:23 +00:00
{
annotation . isPure = * _memberAccess . expression ( ) . annotation ( ) . isPure ;
annotation . isLValue = false ;
}
else
annotation . isLValue = false ;
2015-09-16 14:56:30 +00:00
2017-03-01 18:12:40 +00:00
// TODO some members might be pure, but for example `address(0x123).balance` is not pure
2017-03-01 18:49:15 +00:00
// although every subexpression is, so leaving this limited for now.
2019-04-15 13:33:39 +00:00
if ( auto tt = dynamic_cast < TypeType const * > ( exprType ) )
2017-03-01 18:49:15 +00:00
if ( tt - > actualType ( ) - > category ( ) = = Type : : Category : : Enum )
annotation . isPure = true ;
2020-02-07 11:44:52 +00:00
if (
auto const * functionType = dynamic_cast < FunctionType const * > ( exprType ) ;
functionType & &
functionType - > hasDeclaration ( ) & &
dynamic_cast < FunctionDefinition const * > ( & functionType - > declaration ( ) ) & &
memberName = = " selector "
)
if ( auto const * parentAccess = dynamic_cast < MemberAccess const * > ( & _memberAccess . expression ( ) ) )
{
2020-09-10 10:01:23 +00:00
bool isPure = * parentAccess - > expression ( ) . annotation ( ) . isPure ;
2020-02-07 11:44:52 +00:00
if ( auto const * exprInt = dynamic_cast < Identifier const * > ( & parentAccess - > expression ( ) ) )
if ( exprInt - > name ( ) = = " this " | | exprInt - > name ( ) = = " super " )
2020-09-10 10:01:23 +00:00
isPure = true ;
annotation . isPure = isPure ;
2020-02-07 11:44:52 +00:00
}
2020-09-10 10:01:23 +00:00
2019-04-15 13:33:39 +00:00
if ( auto magicType = dynamic_cast < MagicType const * > ( exprType ) )
2019-01-10 15:28:39 +00:00
{
2018-05-15 11:04:49 +00:00
if ( magicType - > kind ( ) = = MagicType : : Kind : : ABI )
annotation . isPure = true ;
2019-01-14 23:14:10 +00:00
else if ( magicType - > kind ( ) = = MagicType : : Kind : : MetaType & & (
memberName = = " creationCode " | | memberName = = " runtimeCode "
) )
{
annotation . isPure = true ;
2020-05-06 16:26:54 +00:00
ContractType const & accessedContractType = dynamic_cast < ContractType const & > ( * magicType - > typeArgument ( ) ) ;
if (
memberName = = " runtimeCode " & &
! accessedContractType . immutableVariables ( ) . empty ( )
)
m_errorReporter . typeError (
9274 _error ,
_memberAccess . location ( ) ,
" \" runtimeCode \" is not available for contracts containing immutable variables. "
) ;
2020-05-04 16:38:00 +00:00
if ( m_currentContract )
{
// TODO in the same way as with ``new``,
// this is not properly detecting creation-cycles if they go through
// internal library functions or free functions. It will be caught at
// code generation time, but it would of course be better to catch it here.
m_currentContract - > annotation ( ) . contractDependencies . insert ( & accessedContractType . contractDefinition ( ) ) ;
if ( contractDependenciesAreCyclic ( * m_currentContract ) )
m_errorReporter . typeError (
4224 _error ,
_memberAccess . location ( ) ,
" Circular reference for contract code access. "
) ;
}
2019-01-14 23:14:10 +00:00
}
2019-01-22 16:15:55 +00:00
else if ( magicType - > kind ( ) = = MagicType : : Kind : : MetaType & & memberName = = " name " )
annotation . isPure = true ;
2020-04-08 22:08:49 +00:00
else if ( magicType - > kind ( ) = = MagicType : : Kind : : MetaType & & memberName = = " interfaceId " )
annotation . isPure = true ;
2020-05-07 16:24:37 +00:00
else if (
magicType - > kind ( ) = = MagicType : : Kind : : MetaType & &
( memberName = = " min " | | memberName = = " max " )
)
annotation . isPure = true ;
2019-01-10 15:28:39 +00:00
}
2017-03-01 18:12:40 +00:00
2020-09-10 10:01:23 +00:00
if ( ! annotation . isPure . set ( ) )
annotation . isPure = false ;
2015-09-16 14:56:30 +00:00
return false ;
}
bool TypeChecker : : visit ( IndexAccess const & _access )
{
2020-09-10 10:01:23 +00:00
_access . annotation ( ) . isConstant = false ;
2015-09-16 14:56:30 +00:00
_access . baseExpression ( ) . accept ( * this ) ;
TypePointer baseType = type ( _access . baseExpression ( ) ) ;
2019-04-15 13:33:39 +00:00
TypePointer resultType = nullptr ;
2015-09-16 14:56:30 +00:00
bool isLValue = false ;
2020-09-10 10:01:23 +00:00
bool isPure = * _access . baseExpression ( ) . annotation ( ) . isPure ;
2015-09-16 14:56:30 +00:00
Expression const * index = _access . indexExpression ( ) ;
switch ( baseType - > category ( ) )
{
2019-09-03 16:30:00 +00:00
case Type : : Category : : ArraySlice :
{
auto const & arrayType = dynamic_cast < ArraySliceType const & > ( * baseType ) . arrayType ( ) ;
if ( arrayType . location ( ) ! = DataLocation : : CallData | | ! arrayType . isDynamicallySized ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 4802 _error , _access . location ( ) , " Index access is only implemented for slices of dynamic calldata arrays. " ) ;
2019-09-03 16:30:00 +00:00
baseType = & arrayType ;
[[fallthrough]] ;
}
2015-09-16 14:56:30 +00:00
case Type : : Category : : Array :
{
ArrayType const & actualType = dynamic_cast < ArrayType const & > ( * baseType ) ;
if ( ! index )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 9689 _error , _access . location ( ) , " Index expression cannot be omitted. " ) ;
2015-09-16 14:56:30 +00:00
else if ( actualType . isString ( ) )
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 9961 _error , _access . location ( ) , " Index access for string is not possible. " ) ;
2015-09-16 14:56:30 +00:00
index - > accept ( * this ) ;
}
else
{
2019-04-15 16:10:43 +00:00
expectType ( * index , * TypeProvider : : uint256 ( ) ) ;
2018-08-30 03:08:49 +00:00
if ( ! m_errorReporter . hasErrors ( ) )
2019-04-15 13:33:39 +00:00
if ( auto numberType = dynamic_cast < RationalNumberType const * > ( type ( * index ) ) )
2018-08-30 03:08:49 +00:00
{
solAssert ( ! numberType - > isFractional ( ) , " " ) ;
2016-05-10 12:30:24 +00:00
if ( ! actualType . isDynamicallySized ( ) & & actualType . length ( ) < = numberType - > literalValue ( nullptr ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 3383 _error , _access . location ( ) , " Out of bounds array access. " ) ;
2018-08-30 03:08:49 +00:00
}
2015-09-16 14:56:30 +00:00
}
resultType = actualType . baseType ( ) ;
isLValue = actualType . location ( ) ! = DataLocation : : CallData ;
break ;
}
case Type : : Category : : Mapping :
{
MappingType const & actualType = dynamic_cast < MappingType const & > ( * baseType ) ;
if ( ! index )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 1267 _error , _access . location ( ) , " Index expression cannot be omitted. " ) ;
2015-09-16 14:56:30 +00:00
else
expectType ( * index , * actualType . keyType ( ) ) ;
resultType = actualType . valueType ( ) ;
isLValue = true ;
break ;
}
case Type : : Category : : TypeType :
{
TypeType const & typeType = dynamic_cast < TypeType const & > ( * baseType ) ;
2020-10-15 18:00:22 +00:00
if ( auto const * contractType = dynamic_cast < ContractType const * > ( typeType . actualType ( ) ) )
if ( contractType - > contractDefinition ( ) . isLibrary ( ) )
m_errorReporter . typeError ( 2876 _error , _access . location ( ) , " Index access for library types and arrays of libraries are not possible. " ) ;
2015-09-16 14:56:30 +00:00
if ( ! index )
2019-04-17 11:40:50 +00:00
resultType = TypeProvider : : typeType ( TypeProvider : : array ( DataLocation : : Memory , typeType . actualType ( ) ) ) ;
2015-09-16 14:56:30 +00:00
else
{
2019-02-05 12:32:01 +00:00
u256 length = 1 ;
2019-04-15 16:10:43 +00:00
if ( expectType ( * index , * TypeProvider : : uint256 ( ) ) )
2019-02-05 12:32:01 +00:00
{
2019-04-15 13:33:39 +00:00
if ( auto indexValue = dynamic_cast < RationalNumberType const * > ( type ( * index ) ) )
2019-02-05 12:32:01 +00:00
length = indexValue - > literalValue ( nullptr ) ;
else
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 3940 _error , index - > location ( ) , " Integer constant expected. " ) ;
2019-02-05 12:32:01 +00:00
}
2015-09-16 14:56:30 +00:00
else
2019-02-05 12:32:01 +00:00
solAssert ( m_errorReporter . hasErrors ( ) , " Expected errors as expectType returned false " ) ;
2019-04-17 11:40:50 +00:00
resultType = TypeProvider : : typeType ( TypeProvider : : array (
2019-02-05 12:32:01 +00:00
DataLocation : : Memory ,
typeType . actualType ( ) ,
length
) ) ;
2015-09-16 14:56:30 +00:00
}
break ;
}
2016-02-03 20:34:24 +00:00
case Type : : Category : : FixedBytes :
{
FixedBytesType const & bytesType = dynamic_cast < FixedBytesType const & > ( * baseType ) ;
if ( ! index )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 8830 _error , _access . location ( ) , " Index expression cannot be omitted. " ) ;
2016-02-03 20:34:24 +00:00
else
{
2019-04-15 16:10:43 +00:00
if ( ! expectType ( * index , * TypeProvider : : uint256 ( ) ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 6318 _error , _access . location ( ) , " Index expression cannot be represented as an unsigned integer. " ) ;
2019-04-15 13:33:39 +00:00
if ( auto integerType = dynamic_cast < RationalNumberType const * > ( type ( * index ) ) )
2016-02-03 20:34:24 +00:00
if ( bytesType . numBytes ( ) < = integerType - > literalValue ( nullptr ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 1859 _error , _access . location ( ) , " Out of bounds array access. " ) ;
2016-02-03 20:34:24 +00:00
}
2019-04-17 11:40:50 +00:00
resultType = TypeProvider : : fixedBytes ( 1 ) ;
2016-02-03 20:34:24 +00:00
isLValue = false ; // @todo this heavily depends on how it is embedded
break ;
}
2015-09-16 14:56:30 +00:00
default :
2017-05-11 13:26:35 +00:00
m_errorReporter . fatalTypeError (
2020-05-05 22:38:28 +00:00
2614 _error ,
2015-11-04 10:49:26 +00:00
_access . baseExpression ( ) . location ( ) ,
2015-09-16 14:56:30 +00:00
" Indexed expression has to be a type, mapping or array (is " + baseType - > toString ( ) + " ) "
) ;
}
2019-04-15 13:33:39 +00:00
_access . annotation ( ) . type = resultType ;
2015-09-16 14:56:30 +00:00
_access . annotation ( ) . isLValue = isLValue ;
2020-09-10 10:01:23 +00:00
if ( index & & ! * index - > annotation ( ) . isPure )
2017-03-01 18:12:40 +00:00
isPure = false ;
_access . annotation ( ) . isPure = isPure ;
2015-09-16 14:56:30 +00:00
return false ;
}
2019-09-03 16:30:00 +00:00
bool TypeChecker : : visit ( IndexRangeAccess const & _access )
{
2020-09-10 10:01:23 +00:00
_access . annotation ( ) . isConstant = false ;
2019-09-03 16:30:00 +00:00
_access . baseExpression ( ) . accept ( * this ) ;
bool isLValue = false ; // TODO: set this correctly when implementing slices for memory and storage arrays
2020-09-10 10:01:23 +00:00
bool isPure = * _access . baseExpression ( ) . annotation ( ) . isPure ;
2019-09-03 16:30:00 +00:00
if ( Expression const * start = _access . startExpression ( ) )
{
expectType ( * start , * TypeProvider : : uint256 ( ) ) ;
2020-09-10 10:01:23 +00:00
if ( ! * start - > annotation ( ) . isPure )
2019-09-03 16:30:00 +00:00
isPure = false ;
}
if ( Expression const * end = _access . endExpression ( ) )
{
expectType ( * end , * TypeProvider : : uint256 ( ) ) ;
2020-09-10 10:01:23 +00:00
if ( ! * end - > annotation ( ) . isPure )
2019-09-03 16:30:00 +00:00
isPure = false ;
}
2020-09-28 10:12:00 +00:00
_access . annotation ( ) . isLValue = isLValue ;
_access . annotation ( ) . isPure = isPure ;
2019-09-03 16:30:00 +00:00
TypePointer exprType = type ( _access . baseExpression ( ) ) ;
if ( exprType - > category ( ) = = Type : : Category : : TypeType )
{
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 1760 _error , _access . location ( ) , " Types cannot be sliced. " ) ;
2019-09-03 16:30:00 +00:00
_access . annotation ( ) . type = exprType ;
return false ;
}
ArrayType const * arrayType = nullptr ;
if ( auto const * arraySlice = dynamic_cast < ArraySliceType const * > ( exprType ) )
arrayType = & arraySlice - > arrayType ( ) ;
else if ( ! ( arrayType = dynamic_cast < ArrayType const * > ( exprType ) ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 4781 _error , _access . location ( ) , " Index range access is only possible for arrays and array slices. " ) ;
2019-09-03 16:30:00 +00:00
if ( arrayType - > location ( ) ! = DataLocation : : CallData | | ! arrayType - > isDynamicallySized ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . typeError ( 1227 _error , _access . location ( ) , " Index range access is only supported for dynamic calldata arrays. " ) ;
2020-05-13 09:00:47 +00:00
else if ( arrayType - > baseType ( ) - > isDynamicallyEncoded ( ) )
2020-05-26 12:37:31 +00:00
m_errorReporter . typeError ( 2148 _error , _access . location ( ) , " Index range access is not supported for arrays with dynamically encoded base types. " ) ;
2019-09-03 16:30:00 +00:00
_access . annotation ( ) . type = TypeProvider : : arraySlice ( * arrayType ) ;
return false ;
}
2020-04-07 17:31:48 +00:00
vector < Declaration const * > TypeChecker : : cleanOverloadedDeclarations (
Identifier const & _identifier ,
vector < Declaration const * > const & _candidates
)
{
solAssert ( _candidates . size ( ) > 1 , " " ) ;
vector < Declaration const * > uniqueDeclarations ;
for ( Declaration const * declaration : _candidates )
{
solAssert ( declaration , " " ) ;
// the declaration is functionDefinition, eventDefinition or a VariableDeclaration while declarations > 1
solAssert (
dynamic_cast < FunctionDefinition const * > ( declaration ) | |
dynamic_cast < EventDefinition const * > ( declaration ) | |
dynamic_cast < VariableDeclaration const * > ( declaration ) | |
dynamic_cast < MagicVariableDeclaration const * > ( declaration ) ,
" Found overloading involving something not a function, event or a (magic) variable. "
) ;
FunctionTypePointer functionType { declaration - > functionType ( false ) } ;
if ( ! functionType )
functionType = declaration - > functionType ( true ) ;
solAssert ( functionType , " Failed to determine the function type of the overloaded. " ) ;
for ( TypePointer parameter : functionType - > parameterTypes ( ) + functionType - > returnParameterTypes ( ) )
if ( ! parameter )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalDeclarationError ( 3893 _error , _identifier . location ( ) , " Function type can not be used in this context. " ) ;
2020-04-07 17:31:48 +00:00
if ( uniqueDeclarations . end ( ) = = find_if (
uniqueDeclarations . begin ( ) ,
uniqueDeclarations . end ( ) ,
[ & ] ( Declaration const * d )
{
FunctionType const * newFunctionType = d - > functionType ( false ) ;
if ( ! newFunctionType )
newFunctionType = d - > functionType ( true ) ;
return newFunctionType & & functionType - > hasEqualParameterTypes ( * newFunctionType ) ;
}
) )
uniqueDeclarations . push_back ( declaration ) ;
}
return uniqueDeclarations ;
}
2015-09-16 14:56:30 +00:00
bool TypeChecker : : visit ( Identifier const & _identifier )
{
2015-09-21 16:55:58 +00:00
IdentifierAnnotation & annotation = _identifier . annotation ( ) ;
2020-10-05 10:21:30 +00:00
2015-09-16 14:56:30 +00:00
if ( ! annotation . referencedDeclaration )
{
2020-04-07 17:31:48 +00:00
annotation . overloadedDeclarations = cleanOverloadedDeclarations ( _identifier , annotation . candidateDeclarations ) ;
2020-05-27 16:22:04 +00:00
if ( annotation . overloadedDeclarations . empty ( ) )
m_errorReporter . fatalTypeError ( 7593 _error , _identifier . location ( ) , " No candidates for overload resolution found. " ) ;
else if ( annotation . overloadedDeclarations . size ( ) = = 1 )
annotation . referencedDeclaration = * annotation . overloadedDeclarations . begin ( ) ;
else if ( ! annotation . arguments )
2016-12-02 15:24:53 +00:00
{
// The identifier should be a public state variable shadowing other functions
vector < Declaration const * > candidates ;
for ( Declaration const * declaration : annotation . overloadedDeclarations )
{
if ( VariableDeclaration const * variableDeclaration = dynamic_cast < decltype ( variableDeclaration ) > ( declaration ) )
candidates . push_back ( declaration ) ;
}
if ( candidates . empty ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 2144 _error , _identifier . location ( ) , " No matching declaration found after variable lookup. " ) ;
2016-12-02 15:24:53 +00:00
else if ( candidates . size ( ) = = 1 )
annotation . referencedDeclaration = candidates . front ( ) ;
else
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 7589 _error , _identifier . location ( ) , " No unique declaration found after variable lookup. " ) ;
2016-12-02 15:24:53 +00:00
}
2015-09-16 14:56:30 +00:00
else
{
vector < Declaration const * > candidates ;
for ( Declaration const * declaration : annotation . overloadedDeclarations )
{
2017-12-30 12:46:53 +00:00
FunctionTypePointer functionType = declaration - > functionType ( true ) ;
solAssert ( ! ! functionType , " Requested type not present. " ) ;
2019-03-19 16:12:21 +00:00
if ( functionType - > canTakeArguments ( * annotation . arguments ) )
2015-09-16 14:56:30 +00:00
candidates . push_back ( declaration ) ;
}
2019-11-13 13:24:48 +00:00
if ( candidates . size ( ) = = 1 )
2015-09-16 14:56:30 +00:00
annotation . referencedDeclaration = candidates . front ( ) ;
else
2019-11-13 13:24:48 +00:00
{
SecondarySourceLocation ssl ;
for ( Declaration const * declaration : annotation . overloadedDeclarations )
2020-02-03 07:04:21 +00:00
if ( ! declaration - > location ( ) . isValid ( ) )
2019-11-13 17:06:50 +00:00
{
// Try to re-construct function definition
string description ;
for ( auto const & param : declaration - > functionType ( true ) - > parameterTypes ( ) )
description + = ( description . empty ( ) ? " " : " , " ) + param - > toString ( false ) ;
description = " function " + _identifier . name ( ) + " ( " + description + " ) " ;
ssl . append ( " Candidate: " + description , declaration - > location ( ) ) ;
}
else
ssl . append ( " Candidate: " , declaration - > location ( ) ) ;
2019-11-13 13:24:48 +00:00
if ( candidates . empty ( ) )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 9322 _error , _identifier . location ( ) , ssl , " No matching declaration found after argument-dependent lookup. " ) ;
2019-11-13 13:24:48 +00:00
else
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 4487 _error , _identifier . location ( ) , ssl , " No unique declaration found after argument-dependent lookup. " ) ;
2019-11-13 13:24:48 +00:00
}
2015-09-16 14:56:30 +00:00
}
}
solAssert (
! ! annotation . referencedDeclaration ,
" Referenced declaration is null after overload resolution. "
) ;
2020-09-10 10:01:23 +00:00
bool isConstant = false ;
2015-09-16 14:56:30 +00:00
annotation . isLValue = annotation . referencedDeclaration - > isLValue ( ) ;
2015-11-19 17:02:04 +00:00
annotation . type = annotation . referencedDeclaration - > type ( ) ;
2020-01-14 13:00:51 +00:00
solAssert ( annotation . type , " Declaration referenced before type could be determined. " ) ;
2017-03-01 18:12:40 +00:00
if ( auto variableDeclaration = dynamic_cast < VariableDeclaration const * > ( annotation . referencedDeclaration ) )
2020-09-10 10:01:23 +00:00
annotation . isPure = isConstant = variableDeclaration - > isConstant ( ) ;
2017-03-01 18:12:40 +00:00
else if ( dynamic_cast < MagicVariableDeclaration const * > ( annotation . referencedDeclaration ) )
2020-09-10 10:01:23 +00:00
annotation . isPure = dynamic_cast < FunctionType const * > ( annotation . type ) ;
2019-04-15 13:33:39 +00:00
else if ( dynamic_cast < TypeType const * > ( annotation . type ) )
2019-02-18 17:19:55 +00:00
annotation . isPure = true ;
2020-06-16 14:49:31 +00:00
else if ( dynamic_cast < ModuleType const * > ( annotation . type ) )
annotation . isPure = true ;
2020-09-10 10:01:23 +00:00
else
annotation . isPure = false ;
annotation . isConstant = isConstant ;
2018-11-29 09:05:52 +00:00
2020-09-16 09:00:07 +00:00
annotation . requiredLookup =
dynamic_cast < CallableDeclaration const * > ( annotation . referencedDeclaration ) ?
VirtualLookup : : Virtual : VirtualLookup : : Static ;
2018-11-29 09:05:52 +00:00
// Check for deprecated function names.
// The check is done here for the case without an actual function call.
2019-04-15 13:33:39 +00:00
if ( FunctionType const * fType = dynamic_cast < FunctionType const * > ( _identifier . annotation ( ) . type ) )
2018-11-29 09:05:52 +00:00
{
if ( _identifier . name ( ) = = " sha3 " & & fType - > kind ( ) = = FunctionType : : Kind : : KECCAK256 )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
3557 _error ,
2018-11-29 09:05:52 +00:00
_identifier . location ( ) ,
2019-10-21 11:17:12 +00:00
" \" sha3 \" has been deprecated in favour of \" keccak256 \" . "
2018-11-29 09:05:52 +00:00
) ;
else if ( _identifier . name ( ) = = " suicide " & & fType - > kind ( ) = = FunctionType : : Kind : : Selfdestruct )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
8050 _error ,
2018-11-29 09:05:52 +00:00
_identifier . location ( ) ,
2019-10-21 11:17:12 +00:00
" \" suicide \" has been deprecated in favour of \" selfdestruct \" . "
2018-11-29 09:05:52 +00:00
) ;
}
2020-05-05 08:56:18 +00:00
if (
MagicVariableDeclaration const * magicVar =
dynamic_cast < MagicVariableDeclaration const * > ( annotation . referencedDeclaration )
)
if ( magicVar - > type ( ) - > category ( ) = = Type : : Category : : Integer )
{
solAssert ( _identifier . name ( ) = = " now " , " " ) ;
2020-05-19 13:12:56 +00:00
m_errorReporter . typeError (
7359 _error ,
_identifier . location ( ) ,
" \" now \" has been deprecated. Use \" block.timestamp \" instead. "
) ;
2020-05-05 08:56:18 +00:00
}
2015-09-16 14:56:30 +00:00
return false ;
}
void TypeChecker : : endVisit ( ElementaryTypeNameExpression const & _expr )
{
2019-09-04 15:45:12 +00:00
_expr . annotation ( ) . type = TypeProvider : : typeType ( TypeProvider : : fromElementaryTypeName ( _expr . type ( ) . typeName ( ) , _expr . type ( ) . stateMutability ( ) ) ) ;
2017-03-01 18:12:40 +00:00
_expr . annotation ( ) . isPure = true ;
2020-09-10 10:01:23 +00:00
_expr . annotation ( ) . isLValue = false ;
_expr . annotation ( ) . isConstant = false ;
2015-09-16 14:56:30 +00:00
}
void TypeChecker : : endVisit ( Literal const & _literal )
{
2017-01-24 16:38:06 +00:00
if ( _literal . looksLikeAddress ( ) )
{
2018-07-05 13:48:57 +00:00
// Assign type here if it even looks like an address. This prevents double errors for invalid addresses
2019-04-17 11:40:50 +00:00
_literal . annotation ( ) . type = TypeProvider : : payableAddress ( ) ;
2018-02-16 04:24:32 +00:00
2018-06-25 14:25:21 +00:00
string msg ;
2018-10-01 12:36:57 +00:00
if ( _literal . valueWithoutUnderscores ( ) . length ( ) ! = 42 ) // "0x" + 40 hex digits
2018-06-11 10:45:39 +00:00
// looksLikeAddress enforces that it is a hex literal starting with "0x"
2018-06-25 14:25:21 +00:00
msg =
2018-06-11 10:45:39 +00:00
" This looks like an address but is not exactly 40 hex digits. It is " +
2018-10-01 12:36:57 +00:00
to_string ( _literal . valueWithoutUnderscores ( ) . length ( ) - 2 ) +
2018-06-25 14:25:21 +00:00
" hex digits. " ;
2018-02-16 04:24:32 +00:00
else if ( ! _literal . passesAddressChecksum ( ) )
2018-06-25 14:25:21 +00:00
{
msg = " This looks like an address but has an invalid checksum. " ;
if ( ! _literal . getChecksummedAddress ( ) . empty ( ) )
msg + = " Correct checksummed address: \" " + _literal . getChecksummedAddress ( ) + " \" . " ;
}
if ( ! msg . empty ( ) )
2018-02-16 04:24:32 +00:00
m_errorReporter . syntaxError (
2020-05-05 22:38:28 +00:00
9429 _error ,
2017-03-06 12:31:57 +00:00
_literal . location ( ) ,
2018-06-25 14:25:21 +00:00
msg +
" If this is not used as an address, please prepend '00'. " +
2017-10-05 13:28:25 +00:00
" For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals "
2017-03-06 12:31:57 +00:00
) ;
2017-01-24 16:38:06 +00:00
}
2018-04-23 13:54:45 +00:00
2018-03-01 15:58:20 +00:00
if ( _literal . isHexNumber ( ) & & _literal . subDenomination ( ) ! = Literal : : SubDenomination : : None )
2018-07-05 13:48:57 +00:00
m_errorReporter . fatalTypeError (
2020-05-05 22:38:28 +00:00
5145 _error ,
2018-07-05 13:48:57 +00:00
_literal . location ( ) ,
" Hexadecimal numbers cannot be used with unit denominations. "
" You can use an expression of the form \" 0x1234 * 1 day \" instead. "
) ;
2018-04-23 13:54:45 +00:00
if ( _literal . subDenomination ( ) = = Literal : : SubDenomination : : Year )
2018-06-20 22:01:40 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
4820 _error ,
2018-06-20 22:01:40 +00:00
_literal . location ( ) ,
" Using \" years \" as a unit denomination is deprecated. "
) ;
2018-04-23 13:54:45 +00:00
2017-06-22 13:59:00 +00:00
if ( ! _literal . annotation ( ) . type )
2019-04-15 13:33:39 +00:00
_literal . annotation ( ) . type = TypeProvider : : forLiteral ( _literal ) ;
2017-06-22 13:59:00 +00:00
2015-09-16 14:56:30 +00:00
if ( ! _literal . annotation ( ) . type )
2020-05-05 22:38:28 +00:00
m_errorReporter . fatalTypeError ( 2826 _error , _literal . location ( ) , " Invalid literal value. " ) ;
2017-06-22 13:59:00 +00:00
_literal . annotation ( ) . isPure = true ;
2020-09-10 10:01:23 +00:00
_literal . annotation ( ) . isLValue = false ;
_literal . annotation ( ) . isConstant = false ;
2015-09-16 14:56:30 +00:00
}
2020-08-27 12:39:52 +00:00
void TypeChecker : : endVisit ( UsingForDirective const & _usingFor )
{
if ( m_currentContract - > isInterface ( ) )
m_errorReporter . typeError (
9088 _error ,
_usingFor . location ( ) ,
" The \" using for \" directive is not allowed inside interfaces. "
) ;
}
2015-10-07 13:57:17 +00:00
bool TypeChecker : : contractDependenciesAreCyclic (
ContractDefinition const & _contract ,
std : : set < ContractDefinition const * > const & _seenContracts
) const
{
// Naive depth-first search that remembers nodes already seen.
if ( _seenContracts . count ( & _contract ) )
return true ;
set < ContractDefinition const * > seen ( _seenContracts ) ;
seen . insert ( & _contract ) ;
for ( auto const * c : _contract . annotation ( ) . contractDependencies )
if ( contractDependenciesAreCyclic ( * c , seen ) )
return true ;
return false ;
}
2015-11-24 15:34:02 +00:00
Declaration const & TypeChecker : : dereference ( Identifier const & _identifier ) const
2015-09-16 14:56:30 +00:00
{
solAssert ( ! ! _identifier . annotation ( ) . referencedDeclaration , " Declaration not stored. " ) ;
return * _identifier . annotation ( ) . referencedDeclaration ;
}
2015-11-24 15:34:02 +00:00
Declaration const & TypeChecker : : dereference ( UserDefinedTypeName const & _typeName ) const
2015-11-16 23:06:57 +00:00
{
solAssert ( ! ! _typeName . annotation ( ) . referencedDeclaration , " Declaration not stored. " ) ;
return * _typeName . annotation ( ) . referencedDeclaration ;
}
2018-10-10 17:33:45 +00:00
bool TypeChecker : : expectType ( Expression const & _expression , Type const & _expectedType )
2015-09-16 14:56:30 +00:00
{
_expression . accept ( * this ) ;
2020-09-23 14:08:55 +00:00
BoolResult result = type ( _expression ) - > isImplicitlyConvertibleTo ( _expectedType ) ;
if ( ! result )
2016-05-05 22:47:08 +00:00
{
2018-11-30 09:39:21 +00:00
auto errorMsg = " Type " +
type ( _expression ) - > toString ( ) +
" is not implicitly convertible to expected type " +
_expectedType . toString ( ) ;
2016-05-05 22:47:08 +00:00
if (
type ( _expression ) - > category ( ) = = Type : : Category : : RationalNumber & &
2019-04-15 13:33:39 +00:00
dynamic_cast < RationalNumberType const * > ( type ( _expression ) ) - > isFractional ( ) & &
2016-05-10 08:26:53 +00:00
type ( _expression ) - > mobileType ( )
2016-05-05 22:47:08 +00:00
)
2018-11-30 09:39:21 +00:00
{
if ( _expectedType . operator = = ( * type ( _expression ) - > mobileType ( ) ) )
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
4426 _error ,
2018-11-30 09:39:21 +00:00
_expression . location ( ) ,
errorMsg + " , but it can be explicitly converted. "
) ;
else
2020-09-23 14:08:55 +00:00
m_errorReporter . typeErrorConcatenateDescriptions (
2020-05-05 22:38:28 +00:00
2326 _error ,
2018-11-30 09:39:21 +00:00
_expression . location ( ) ,
errorMsg +
" . Try converting to type " +
type ( _expression ) - > mobileType ( ) - > toString ( ) +
2020-09-23 14:08:55 +00:00
" or use an explicit conversion. " ,
result . message ( )
2018-11-30 09:39:21 +00:00
) ;
}
2016-05-05 22:47:08 +00:00
else
2020-09-23 14:08:55 +00:00
m_errorReporter . typeErrorConcatenateDescriptions (
7407 _error ,
_expression . location ( ) ,
errorMsg + " . " ,
result . message ( )
) ;
2018-10-10 17:33:45 +00:00
return false ;
2017-06-22 14:14:14 +00:00
}
2018-10-10 17:33:45 +00:00
return true ;
2015-09-16 14:56:30 +00:00
}
2020-03-10 17:15:50 +00:00
void TypeChecker : : requireLValue ( Expression const & _expression , bool _ordinaryAssignment )
2015-09-16 14:56:30 +00:00
{
2020-04-09 10:48:57 +00:00
_expression . annotation ( ) . willBeWrittenTo = true ;
2020-03-10 17:15:50 +00:00
_expression . annotation ( ) . lValueOfOrdinaryAssignment = _ordinaryAssignment ;
2015-09-16 14:56:30 +00:00
_expression . accept ( * this ) ;
2016-12-13 02:59:53 +00:00
2020-09-10 10:01:23 +00:00
if ( * _expression . annotation ( ) . isLValue )
2019-08-12 15:06:10 +00:00
return ;
2020-05-21 01:49:31 +00:00
auto [ errorId , description ] = [ & ] ( ) - > tuple < ErrorId , string > {
2020-09-10 10:01:23 +00:00
if ( * _expression . annotation ( ) . isConstant )
2020-05-21 01:49:31 +00:00
return { 6520 _error , " Cannot assign to a constant variable. " } ;
2019-08-12 15:06:10 +00:00
2019-08-13 16:58:50 +00:00
if ( auto indexAccess = dynamic_cast < IndexAccess const * > ( & _expression ) )
2019-08-12 15:06:10 +00:00
{
2019-08-13 16:58:50 +00:00
if ( type ( indexAccess - > baseExpression ( ) ) - > category ( ) = = Type : : Category : : FixedBytes )
2020-05-26 12:37:31 +00:00
return { 4360 _error , " Single bytes in fixed bytes arrays cannot be modified. " } ;
2019-08-13 16:58:50 +00:00
else if ( auto arrayType = dynamic_cast < ArrayType const * > ( type ( indexAccess - > baseExpression ( ) ) ) )
if ( arrayType - > dataStoredIn ( DataLocation : : CallData ) )
2020-05-26 12:37:31 +00:00
return { 6182 _error , " Calldata arrays are read-only. " } ;
2019-08-12 15:06:10 +00:00
}
2019-08-13 16:58:50 +00:00
if ( auto memberAccess = dynamic_cast < MemberAccess const * > ( & _expression ) )
2019-08-12 15:06:10 +00:00
{
2019-08-13 16:58:50 +00:00
if ( auto structType = dynamic_cast < StructType const * > ( type ( memberAccess - > expression ( ) ) ) )
2019-08-12 15:06:10 +00:00
{
2019-08-13 16:58:50 +00:00
if ( structType - > dataStoredIn ( DataLocation : : CallData ) )
2020-05-26 12:37:31 +00:00
return { 4156 _error , " Calldata structs are read-only. " } ;
2019-08-12 15:06:10 +00:00
}
2019-09-18 12:58:20 +00:00
else if ( dynamic_cast < ArrayType const * > ( type ( memberAccess - > expression ( ) ) ) )
if ( memberAccess - > memberName ( ) = = " length " )
2020-05-21 01:49:31 +00:00
return { 7567 _error , " Member \" length \" is read-only and cannot be used to resize arrays. " } ;
2019-08-12 15:06:10 +00:00
}
2019-08-13 16:58:50 +00:00
if ( auto identifier = dynamic_cast < Identifier const * > ( & _expression ) )
if ( auto varDecl = dynamic_cast < VariableDeclaration const * > ( identifier - > annotation ( ) . referencedDeclaration ) )
if ( varDecl - > isExternalCallableParameter ( ) & & dynamic_cast < ReferenceType const * > ( identifier - > annotation ( ) . type ) )
2020-05-21 01:49:31 +00:00
return { 7128 _error , " External function arguments of reference type are read-only. " } ;
return { 4247 _error , " Expression has to be an lvalue. " } ;
} ( ) ;
2019-08-12 15:06:10 +00:00
2020-05-21 01:49:31 +00:00
m_errorReporter . typeError ( errorId , _expression . location ( ) , description ) ;
2015-09-16 14:56:30 +00:00
}
2020-06-11 22:16:24 +00:00
2020-10-22 17:19:14 +00:00
bool TypeChecker : : useABICoderV2 ( ) const
2020-06-11 22:16:24 +00:00
{
solAssert ( m_currentSourceUnit , " " ) ;
if ( m_currentContract )
solAssert ( m_currentSourceUnit = = & m_currentContract - > sourceUnit ( ) , " " ) ;
2020-10-22 17:19:14 +00:00
return * m_currentSourceUnit - > annotation ( ) . useABICoderV2 ;
2020-06-11 22:16:24 +00:00
}