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>
2020-10-29 14:00:27 +00:00
# include <libyul/AST.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 )
2020-12-01 09:24:50 +00:00
m_errorReporter . fatalTypeError (
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. "
) ;
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 ( ) ;
2020-12-01 09:24:50 +00:00
if ( auto const * contractType = dynamic_cast < ContractType const * > ( typeTypePtr - > actualType ( ) ) )
wrongType = contractType - > isSuper ( ) ;
else if ( typeCategory ! = Type : : Category : : Integer )
2020-05-07 16:24:37 +00:00
wrongType = true ;
}
else
wrongType = true ;
if ( wrongType )
2020-12-01 09:24:50 +00:00
m_errorReporter . fatalTypeError (
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
) ;
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
2020-08-11 09:18:22 +00:00
if ( ! _function . modifiers ( ) . empty ( ) & & _function . isFree ( ) )
m_errorReporter . syntaxError ( 5811 _error , _function . location ( ) , " Free functions cannot have modifiers. " ) ;
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
) ;
2020-08-11 09:18:22 +00:00
Declaration const * decl = & dereference ( modifier - > name ( ) ) ;
2017-06-23 16:55:47 +00:00
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
2020-08-11 09:18:22 +00:00
_modifier . name ( ) . accept ( * this ) ;
2015-09-16 14:56:30 +00:00
2020-08-11 09:18:22 +00:00
auto const * declaration = & dereference ( _modifier . name ( ) ) ;
2015-09-16 14:56:30 +00:00
vector < ASTPointer < VariableDeclaration > > emptyParameterList ;
vector < ASTPointer < VariableDeclaration > > const * parameters = nullptr ;
if ( auto modifierDecl = dynamic_cast < ModifierDefinition const * > ( declaration ) )
2020-11-16 19:12:25 +00:00
{
2015-09-16 14:56:30 +00:00
parameters = & modifierDecl - > parameters ( ) ;
2020-11-16 19:12:25 +00:00
if ( auto const * modifierContract = dynamic_cast < ContractDefinition const * > ( modifierDecl - > scope ( ) ) )
if ( m_currentContract )
{
if ( ! contains ( m_currentContract - > annotation ( ) . linearizedBaseContracts , modifierContract ) )
m_errorReporter . typeError (
9428 _error ,
_modifier . location ( ) ,
" Can only use modifiers defined in the current contract or in base contracts. "
) ;
}
}
2015-09-16 14:56:30 +00:00
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 , " " ) ;
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
}
2020-11-05 13:39:39 +00:00
else if ( ! identifierInfo . suffix . empty ( ) )
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. " ) ;
2020-11-05 13:39:39 +00:00
if ( ! identifierInfo . suffix . empty ( ) )
2019-07-09 09:11:40 +00:00
{
2020-11-05 13:39:39 +00:00
string const & suffix = identifierInfo . suffix ;
solAssert ( ( set < string > { " offset " , " slot " , " length " } ) . count ( suffix ) , " " ) ;
if ( var - > isStateVariable ( ) | | var - > type ( ) - > dataStoredIn ( DataLocation : : Storage ) )
2017-04-21 17:13:46 +00:00
{
2020-11-05 13:39:39 +00:00
if ( suffix ! = " slot " & & suffix ! = " offset " )
2020-02-24 14:53:32 +00:00
{
2020-11-05 13:39:39 +00:00
m_errorReporter . typeError ( 4656 _error , _identifier . location , " State variables only support \" .slot \" and \" .offset \" . " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2020-02-24 14:53:32 +00:00
}
2020-11-05 13:39:39 +00:00
else if ( _context = = yul : : IdentifierContext : : LValue )
2020-02-24 14:53:32 +00:00
{
2020-11-05 13:39:39 +00:00
if ( var - > isStateVariable ( ) )
{
m_errorReporter . typeError ( 4713 _error , _identifier . location , " State variables cannot be assigned to - you have to use \" sstore() \" . " ) ;
return false ;
}
else if ( suffix ! = " slot " )
{
m_errorReporter . typeError ( 9739 _error , _identifier . location , " Only .slot can be assigned to. " ) ;
return false ;
}
}
}
else if (
auto const * arrayType = dynamic_cast < ArrayType const * > ( var - > type ( ) ) ;
arrayType & & arrayType - > isDynamicallySized ( ) & & arrayType - > dataStoredIn ( DataLocation : : CallData )
)
{
if ( suffix ! = " offset " & & suffix ! = " length " )
2020-02-24 14:53:32 +00:00
{
2020-11-05 13:39:39 +00:00
m_errorReporter . typeError ( 1536 _error , _identifier . location , " Calldata variables only support \" .offset \" and \" .length \" . " ) ;
2020-06-11 16:46:31 +00:00
return false ;
2020-02-24 14:53:32 +00:00
}
2020-11-05 13:39:39 +00:00
}
else
{
m_errorReporter . typeError ( 3622 _error , _identifier . location , " The suffix \" . " + suffix + " \" is not supported by this variable or type. " ) ;
return false ;
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-11-05 13:39:39 +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-11-05 13:39:39 +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
{
2020-11-05 13:39:39 +00:00
if (
auto const * arrayType = dynamic_cast < ArrayType const * > ( var - > type ( ) ) ;
arrayType & & arrayType - > isDynamicallySized ( ) & & arrayType - > dataStoredIn ( DataLocation : : CallData )
)
m_errorReporter . typeError ( 1397 _error , _identifier . location , " Call data elements cannot be accessed directly. Use \" .offset \" and \" .length \" to access the calldata offset and length of this array and then use \" calldatacopy \" . " ) ;
2017-07-11 11:37:34 +00:00
else
2020-11-05 13:39:39 +00:00
{
solAssert ( ! var - > type ( ) - > dataStoredIn ( DataLocation : : CallData ) , " " ) ;
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-11-05 13:39:39 +00:00
}
2020-06-11 16:46:31 +00:00
return false ;
2017-04-11 19:12:17 +00:00
}
}
2020-11-05 13:39:39 +00:00
else if ( ! identifierInfo . suffix . empty ( ) )
2018-08-07 12:17:56 +00:00
{
2020-11-05 13:39:39 +00:00
m_errorReporter . typeError ( 7944 _error , _identifier . location , " The suffixes \" .offset \" , \" .slot \" and \" .length \" can only be used with 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 \" . " ) ;
2020-11-05 17:03:32 +00:00
if ( ! _function . returnParameters ( ) . empty ( ) | | ! _function . parameters ( ) . empty ( ) )
2019-09-09 16:22:02 +00:00
{
2020-11-05 17:03:32 +00:00
if (
_function . returnParameters ( ) . size ( ) ! = 1 | |
* type ( * _function . returnParameters ( ) . front ( ) ) ! = * TypeProvider : : bytesMemory ( ) | |
_function . parameters ( ) . size ( ) ! = 1 | |
* type ( * _function . parameters ( ) . front ( ) ) ! = * TypeProvider : : bytesCalldata ( )
)
m_errorReporter . typeError (
5570 _error ,
_function . returnParameterList ( ) - > location ( ) ,
" Fallback function either has to have the signature \" fallback() \" or \" fallback(bytes calldata) returns (bytes memory) \" . "
) ;
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 ;
2020-11-24 11:27:55 +00:00
if ( auto memberAccess = dynamic_cast < MemberAccess const * > ( & _functionCall . expression ( ) ) )
{
if ( dynamic_cast < FunctionDefinition const * > ( memberAccess - > annotation ( ) . referencedDeclaration ) )
_functionCall . expression ( ) . annotation ( ) . calledDirectly = true ;
}
else if ( auto identifier = dynamic_cast < Identifier const * > ( & _functionCall . expression ( ) ) )
if ( dynamic_cast < FunctionDefinition const * > ( identifier - > annotation ( ) . referencedDeclaration ) )
_functionCall . expression ( ) . annotation ( ) . calledDirectly = true ;
2018-10-18 21:53:59 +00:00
// 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 - > 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
2020-12-01 09:34:45 +00:00
{
if ( auto const * contractType = dynamic_cast < ContractType const * > ( actualType ) )
if ( contractType - > isSuper ( ) )
m_errorReporter . fatalTypeError (
1744 _error ,
_functionCall . location ( ) ,
" Cannot convert to the super type. "
) ;
2018-10-18 21:53:59 +00:00
funcCallAnno . kind = FunctionCallKind : : TypeConversion ;
2020-12-01 09:34:45 +00:00
}
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 ;
}
2020-11-02 13:10:37 +00:00
if (
expressionFunctionType - > valueSet ( ) | |
expressionFunctionType - > gasSet ( ) | |
expressionFunctionType - > saltSet ( )
)
m_errorReporter . typeError (
1645 _error ,
_functionCallOptions . location ( ) ,
" Function call options have already been set, you have to combine them into a single "
" {...}-option. "
) ;
auto setCheckOption = [ & ] ( bool & _option , string const & _name )
2020-01-22 14:42:50 +00:00
{
2020-11-02 13:10:37 +00:00
if ( _option )
2020-01-22 14:42:50 +00:00
m_errorReporter . typeError (
2020-05-05 22:38:28 +00:00
9886 _error ,
2020-01-22 14:42:50 +00:00
_functionCallOptions . location ( ) ,
" 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 )
{
2020-11-02 13:10:37 +00:00
setCheckOption ( setSalt , " salt " ) ;
2020-01-22 14:42:50 +00:00
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 ( ) ) ;
2020-11-02 13:10:37 +00:00
setCheckOption ( setValue , " value " ) ;
2020-01-22 14:42:50 +00:00
}
}
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 ( ) ) ;
2020-11-02 13:10:37 +00:00
setCheckOption ( setGas , " gas " ) ;
2020-01-22 14:42:50 +00:00
}
}
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 ( ) ) )
{
2020-08-11 09:18:22 +00:00
auto contract = dynamic_cast < ContractDefinition const * > ( & dereference ( contractName - > pathNode ( ) ) ) ;
2015-11-16 23:06:57 +00:00
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 ( ) )
2020-10-14 09:17:53 +00:00
if ( auto typeType = dynamic_cast < TypeType const * > ( exprType ) )
{
auto contractType = dynamic_cast < ContractType const * > ( typeType - > actualType ( ) ) ;
if ( contractType & & contractType - > isSuper ( ) )
2020-10-30 14:40:06 +00:00
requiredLookup = VirtualLookup : : Super ;
2020-10-14 09:17:53 +00:00
}
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 ( ) ) ;
2020-12-01 09:24:50 +00:00
solAssert ( ! accessedContractType . isSuper ( ) , " " ) ;
2020-05-06 16:26:54 +00:00
if (
memberName = = " runtimeCode " & &
! accessedContractType . immutableVariables ( ) . empty ( )
)
m_errorReporter . typeError (
9274 _error ,
_memberAccess . location ( ) ,
" \" runtimeCode \" is not available for contracts containing immutable variables. "
) ;
2020-12-01 09:24:50 +00:00
if ( m_currentContract )
2020-05-04 16:38:00 +00:00
{
// 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 ;
}
2020-08-11 09:18:22 +00:00
void TypeChecker : : endVisit ( IdentifierPath const & _identifierPath )
{
if (
dynamic_cast < CallableDeclaration const * > ( _identifierPath . annotation ( ) . referencedDeclaration ) & &
_identifierPath . path ( ) . size ( ) = = 1
)
_identifierPath . annotation ( ) . requiredLookup = VirtualLookup : : Virtual ;
else
_identifierPath . annotation ( ) . requiredLookup = VirtualLookup : : Static ;
}
void TypeChecker : : endVisit ( UserDefinedTypeName const & _userDefinedTypeName )
{
if ( ! _userDefinedTypeName . annotation ( ) . type )
_userDefinedTypeName . annotation ( ) . type = _userDefinedTypeName . pathNode ( ) . annotation ( ) . referencedDeclaration - > type ( ) ;
}
2015-09-16 14:56:30 +00:00
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'. " +
2020-11-18 14:20:34 +00:00
" For more information please see https://docs.soliditylang.org/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 ;
}
2020-08-11 09:18:22 +00:00
Declaration const & TypeChecker : : dereference ( IdentifierPath const & _path ) const
2015-11-16 23:06:57 +00:00
{
2020-08-11 09:18:22 +00:00
solAssert ( ! ! _path . annotation ( ) . referencedDeclaration , " Declaration not stored. " ) ;
return * _path . annotation ( ) . referencedDeclaration ;
2015-11-16 23:06:57 +00:00
}
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
}