mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Correctly name builtin functions in error messages.
This commit is contained in:
parent
3fb42f60b4
commit
843171c70f
@ -10,6 +10,7 @@ Compiler Features:
|
||||
* SMTChecker: Output values for ``block.*``, ``msg.*`` and ``tx.*`` variables that are present in the called functions.
|
||||
* Standard JSON: Accept nested brackets in step sequences passed to ``settings.optimizer.details.yulDetails.optimizerSteps``.
|
||||
* Standard JSON: Add ``settings.debug.debugInfo`` option for selecting how much extra debug information should be included in the produced EVM assembly and Yul code.
|
||||
* TypeChecker: Improve error message in implicit function type conversions failures from and to builtin function types.
|
||||
|
||||
|
||||
Bugfixes:
|
||||
|
@ -37,7 +37,7 @@ namespace solidity::frontend
|
||||
namespace
|
||||
{
|
||||
/// Magic variables get negative ids for easy differentiation
|
||||
int magicVariableToID(std::string const& _name)
|
||||
int magicVariableToID(std::string const& _name) // TODO(pr): I think that should be a FunctionType::Kind instead of string.
|
||||
{
|
||||
if (_name == "abi") return -1;
|
||||
else if (_name == "addmod") return -2;
|
||||
@ -71,37 +71,45 @@ inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariable
|
||||
return make_shared<MagicVariableDeclaration>(magicVariableToID(_name), _name, _type);
|
||||
};
|
||||
|
||||
static auto const magicFunDecl = [](FunctionType const* _type) -> shared_ptr<MagicVariableDeclaration> {
|
||||
auto const kind = _type->kind();
|
||||
return make_shared<MagicVariableDeclaration>(
|
||||
magicVariableToID(string(FunctionType::magicName(kind))),
|
||||
ASTString(FunctionType::magicName(kind)),
|
||||
_type
|
||||
);
|
||||
};
|
||||
|
||||
return {
|
||||
magicVarDecl("abi", TypeProvider::magic(MagicType::Kind::ABI)),
|
||||
magicVarDecl("addmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, false, StateMutability::Pure)),
|
||||
magicVarDecl("assert", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)),
|
||||
magicVarDecl("block", TypeProvider::magic(MagicType::Kind::Block)),
|
||||
magicVarDecl("blockhash", TypeProvider::function(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)),
|
||||
magicVarDecl("ecrecover", TypeProvider::function(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)),
|
||||
magicVarDecl("gasleft", TypeProvider::function(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, false, StateMutability::View)),
|
||||
magicVarDecl("keccak256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)),
|
||||
magicVarDecl("msg", TypeProvider::magic(MagicType::Kind::Message)),
|
||||
magicVarDecl("mulmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)),
|
||||
magicVarDecl("now", TypeProvider::uint256()),
|
||||
magicVarDecl("require", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)),
|
||||
magicVarDecl("require", TypeProvider::function(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)),
|
||||
magicVarDecl("revert", TypeProvider::function(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
|
||||
magicVarDecl("revert", TypeProvider::function(strings{"string memory"}, strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
|
||||
magicVarDecl("ripemd160", TypeProvider::function(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, false, StateMutability::Pure)),
|
||||
magicVarDecl("selfdestruct", TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)),
|
||||
magicVarDecl("sha256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, false, StateMutability::Pure)),
|
||||
magicVarDecl("sha3", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)),
|
||||
magicVarDecl("suicide", TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)),
|
||||
magicVarDecl("tx", TypeProvider::magic(MagicType::Kind::Transaction)),
|
||||
// magic functions
|
||||
magicFunDecl(TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)),
|
||||
magicFunDecl(TypeProvider::function(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, false, StateMutability::View)),
|
||||
magicFunDecl(TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings{"string memory"}, strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, false, StateMutability::Pure)),
|
||||
magicFunDecl(TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)),
|
||||
magicFunDecl(TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, false, StateMutability::Pure)),
|
||||
// Accepts a MagicType that can be any contract type or an Integer type and returns a
|
||||
// MagicType. The TypeChecker handles the correctness of the input and output types.
|
||||
magicVarDecl("type", TypeProvider::function(
|
||||
strings{},
|
||||
strings{},
|
||||
FunctionType::Kind::MetaType,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
)),
|
||||
magicFunDecl(TypeProvider::function(strings{}, strings{}, FunctionType::Kind::MetaType, true, StateMutability::Pure)),
|
||||
|
||||
// Aliases: sha3 and suicide() are an alias() to keccak256() and selfdestruct()
|
||||
magicVarDecl("sha3", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)),
|
||||
magicVarDecl("suicide", TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)),
|
||||
|
||||
// magic variables
|
||||
magicVarDecl("abi", TypeProvider::magic(MagicType::Kind::ABI)),
|
||||
magicVarDecl("block", TypeProvider::magic(MagicType::Kind::Block)),
|
||||
magicVarDecl("msg", TypeProvider::magic(MagicType::Kind::Message)),
|
||||
magicVarDecl("now", TypeProvider::uint256()),
|
||||
magicVarDecl("tx", TypeProvider::magic(MagicType::Kind::Transaction)),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -467,19 +467,23 @@ bool AddressType::operator==(Type const& _other) const
|
||||
|
||||
MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const
|
||||
{
|
||||
auto const magicFunc = [](FunctionType const* _functionType) -> MemberList::Member {
|
||||
return {FunctionType::magicName(_functionType->kind()), _functionType};
|
||||
};
|
||||
|
||||
MemberList::MemberMap members = {
|
||||
{"balance", TypeProvider::uint256()},
|
||||
{"code", TypeProvider::array(DataLocation::Memory)},
|
||||
{"codehash", TypeProvider::fixedBytes(32)},
|
||||
{"call", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)},
|
||||
{"callcode", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)},
|
||||
{"delegatecall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false, StateMutability::NonPayable)},
|
||||
{"staticcall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}
|
||||
{"balance"sv, TypeProvider::uint256()},
|
||||
{"code"sv, TypeProvider::array(DataLocation::Memory)},
|
||||
{"codehash"sv, TypeProvider::fixedBytes(32)},
|
||||
magicFunc(TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)),
|
||||
magicFunc(TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)),
|
||||
magicFunc(TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false, StateMutability::NonPayable)),
|
||||
magicFunc(TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View))
|
||||
};
|
||||
if (m_stateMutability == StateMutability::Payable)
|
||||
{
|
||||
members.emplace_back(MemberList::Member{"send", TypeProvider::function(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send, false, StateMutability::NonPayable)});
|
||||
members.emplace_back(MemberList::Member{"transfer", TypeProvider::function(strings{"uint"}, strings(), FunctionType::Kind::Transfer, false, StateMutability::NonPayable)});
|
||||
members.emplace_back(magicFunc(TypeProvider::function(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send, false, StateMutability::NonPayable)));
|
||||
members.emplace_back(magicFunc(TypeProvider::function(strings{"uint"}, strings(), FunctionType::Kind::Transfer, false, StateMutability::NonPayable)));
|
||||
}
|
||||
return members;
|
||||
}
|
||||
@ -1806,28 +1810,32 @@ MemberList::MemberMap ArrayType::nativeMembers(ASTNode const*) const
|
||||
members.emplace_back("length", TypeProvider::uint256());
|
||||
if (isDynamicallySized() && location() == DataLocation::Storage)
|
||||
{
|
||||
auto const magicBoundFunc = [](FunctionType const* _functionType) -> MemberList::Member {
|
||||
return {FunctionType::magicName(_functionType->kind()), _functionType->asBoundFunction()};
|
||||
};
|
||||
Type const* thisAsPointer = TypeProvider::withLocation(this, location(), true);
|
||||
members.emplace_back("push", TypeProvider::function(
|
||||
|
||||
members.emplace_back(magicBoundFunc(TypeProvider::function(
|
||||
TypePointers{thisAsPointer},
|
||||
TypePointers{baseType()},
|
||||
strings{string()},
|
||||
strings{string()},
|
||||
FunctionType::Kind::ArrayPush
|
||||
)->asBoundFunction());
|
||||
members.emplace_back("push", TypeProvider::function(
|
||||
)));
|
||||
members.emplace_back(magicBoundFunc(TypeProvider::function(
|
||||
TypePointers{thisAsPointer, baseType()},
|
||||
TypePointers{},
|
||||
strings{string(),string()},
|
||||
strings{},
|
||||
FunctionType::Kind::ArrayPush
|
||||
)->asBoundFunction());
|
||||
members.emplace_back("pop", TypeProvider::function(
|
||||
)));
|
||||
members.emplace_back(magicBoundFunc(TypeProvider::function(
|
||||
TypePointers{thisAsPointer},
|
||||
TypePointers{},
|
||||
strings{string()},
|
||||
strings{},
|
||||
FunctionType::Kind::ArrayPop
|
||||
)->asBoundFunction());
|
||||
)));
|
||||
}
|
||||
}
|
||||
return members;
|
||||
@ -3030,22 +3038,96 @@ string FunctionType::canonicalName() const
|
||||
return "function";
|
||||
}
|
||||
|
||||
string_view FunctionType::magicName(Kind _kind) // TODO(pr): maybe call it languageIdentifier(.) instead
|
||||
{
|
||||
switch (_kind)
|
||||
{
|
||||
// magic funcs and vars
|
||||
case Kind::AddMod: return "addmod"sv;
|
||||
case Kind::Assert: return "assert"sv;
|
||||
case Kind::BlockHash: return "blockhash"sv;
|
||||
case Kind::ECRecover: return "ecrecover"sv;
|
||||
case Kind::Require: return "require"sv;
|
||||
case Kind::GasLeft: return "gasleft"sv;
|
||||
case Kind::KECCAK256: return "keccak256"sv; // NB: sha3 is an alias to keccak256
|
||||
case Kind::MulMod: return "mulmod"sv;
|
||||
case Kind::Revert: return "revert"sv;
|
||||
case Kind::RIPEMD160: return "ripemd160"sv;
|
||||
case Kind::Selfdestruct: return "selfdestruct"sv; // NB: suicide() is an alias to selfdestruct()
|
||||
case Kind::SHA256: return "sha256"sv;
|
||||
case Kind::MetaType: return "type"sv;
|
||||
|
||||
// native members: ArrayType
|
||||
case Kind::ArrayPop: return "pop"sv;
|
||||
case Kind::ArrayPush: return "push"sv;
|
||||
|
||||
// native members: AddressType
|
||||
case Kind::BareCall: return "call"sv;
|
||||
case Kind::BareCallCode: return "callcode"sv;
|
||||
case Kind::BareDelegateCall: return "delegatecall"sv;
|
||||
case Kind::BareStaticCall: return "staticcall"sv;
|
||||
case Kind::Send: return "send"sv;
|
||||
case Kind::Transfer: return "transfer"sv;
|
||||
|
||||
// FunctionType
|
||||
case Kind::SetValue: return "value"sv;
|
||||
case Kind::SetGas: return "gas"sv;
|
||||
|
||||
// TypeType
|
||||
case Kind::Unwrap: return "unwrap"sv;
|
||||
case Kind::Wrap: return "wrap"sv;
|
||||
case Kind::BytesConcat: return "concat"sv;
|
||||
|
||||
// MagicType
|
||||
case Kind::ABIEncode: return "encode"sv;
|
||||
case Kind::ABIDecode: return "decode"sv;
|
||||
case Kind::ABIEncodePacked: return "encodePacked"sv;
|
||||
case Kind::ABIEncodeWithSelector: return "encodeWithSelector"sv;
|
||||
case Kind::ABIEncodeWithSignature: return "encodeWithSignature"sv;
|
||||
|
||||
|
||||
// user defined
|
||||
case Kind::Error:
|
||||
case Kind::Event:
|
||||
case Kind::Creation:
|
||||
case Kind::Declaration:
|
||||
case Kind::DelegateCall:
|
||||
case Kind::External:
|
||||
case Kind::Internal:
|
||||
case Kind::ObjectCreation:
|
||||
break;
|
||||
}
|
||||
|
||||
return ""sv;
|
||||
}
|
||||
|
||||
string FunctionType::toString(bool _short) const
|
||||
{
|
||||
string name = "function ";
|
||||
if (m_kind == Kind::Declaration)
|
||||
string name;
|
||||
|
||||
if (m_kind == Kind::Event)
|
||||
name += "event " + m_declaration->name();
|
||||
else if (m_kind == Kind::Error)
|
||||
name += "error " + m_declaration->name();
|
||||
else if (magicName(m_kind) != "")
|
||||
name += magicName(m_kind);
|
||||
else if (m_kind == Kind::Declaration)
|
||||
{
|
||||
name += "function ";
|
||||
auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(m_declaration);
|
||||
solAssert(functionDefinition, "");
|
||||
if (auto const* contract = dynamic_cast<ContractDefinition const*>(functionDefinition->scope()))
|
||||
name += *contract->annotation().canonicalName + ".";
|
||||
name += functionDefinition->name();
|
||||
}
|
||||
else
|
||||
name += "function ";
|
||||
|
||||
name += '(';
|
||||
for (auto it = m_parameterTypes.begin(); it != m_parameterTypes.end(); ++it)
|
||||
name += (*it)->toString(_short) + (it + 1 == m_parameterTypes.end() ? "" : ",");
|
||||
name += ")";
|
||||
if (m_stateMutability != StateMutability::NonPayable)
|
||||
if (m_stateMutability != StateMutability::NonPayable && m_kind != Kind::Error)
|
||||
name += " " + stateMutabilityToString(m_stateMutability);
|
||||
if (m_kind == Kind::External)
|
||||
name += " external";
|
||||
@ -3190,6 +3272,11 @@ FunctionTypePointer FunctionType::interfaceFunctionType() const
|
||||
|
||||
MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const
|
||||
{
|
||||
auto const magicFunc = [](FunctionType const* _functionType) -> MemberList::Member {
|
||||
return {FunctionType::magicName(_functionType->kind()), _functionType};
|
||||
};
|
||||
|
||||
|
||||
switch (m_kind)
|
||||
{
|
||||
case Kind::Declaration:
|
||||
@ -3229,40 +3316,34 @@ MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const
|
||||
if (m_kind != Kind::BareDelegateCall)
|
||||
{
|
||||
if (isPayable())
|
||||
members.emplace_back(
|
||||
"value",
|
||||
TypeProvider::function(
|
||||
parseElementaryTypeVector({"uint"}),
|
||||
TypePointers{copyAndSetCallOptions(false, true, false)},
|
||||
strings(1, ""),
|
||||
strings(1, ""),
|
||||
Kind::SetValue,
|
||||
false,
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
m_gasSet,
|
||||
m_valueSet,
|
||||
m_saltSet
|
||||
)
|
||||
);
|
||||
}
|
||||
if (m_kind != Kind::Creation)
|
||||
members.emplace_back(
|
||||
"gas",
|
||||
TypeProvider::function(
|
||||
members.emplace_back(magicFunc(TypeProvider::function(
|
||||
parseElementaryTypeVector({"uint"}),
|
||||
TypePointers{copyAndSetCallOptions(true, false, false)},
|
||||
TypePointers{copyAndSetCallOptions(false, true, false)},
|
||||
strings(1, ""),
|
||||
strings(1, ""),
|
||||
Kind::SetGas,
|
||||
Kind::SetValue,
|
||||
false,
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
m_gasSet,
|
||||
m_valueSet,
|
||||
m_saltSet
|
||||
)
|
||||
);
|
||||
)));
|
||||
}
|
||||
if (m_kind != Kind::Creation)
|
||||
members.emplace_back(magicFunc(TypeProvider::function(
|
||||
parseElementaryTypeVector({"uint"}),
|
||||
TypePointers{copyAndSetCallOptions(true, false, false)},
|
||||
strings(1, ""),
|
||||
strings(1, ""),
|
||||
Kind::SetGas,
|
||||
false,
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
m_gasSet,
|
||||
m_valueSet,
|
||||
m_saltSet
|
||||
)));
|
||||
return members;
|
||||
}
|
||||
case Kind::DelegateCall:
|
||||
@ -3720,6 +3801,11 @@ vector<tuple<string, Type const*>> TypeType::makeStackItems() const
|
||||
|
||||
MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) const
|
||||
{
|
||||
auto const magicFunc = [](FunctionType const* _functionType) -> MemberList::Member {
|
||||
return {FunctionType::magicName(_functionType->kind()), _functionType};
|
||||
};
|
||||
|
||||
|
||||
MemberList::MemberMap members;
|
||||
if (m_actualType->category() == Category::Contract)
|
||||
{
|
||||
@ -3794,8 +3880,7 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
|
||||
else if (m_actualType->category() == Category::UserDefinedValueType)
|
||||
{
|
||||
auto& userDefined = dynamic_cast<UserDefinedValueType const&>(*m_actualType);
|
||||
members.emplace_back(
|
||||
"wrap",
|
||||
members.emplace_back(magicFunc(
|
||||
TypeProvider::function(
|
||||
TypePointers{&userDefined.underlyingType()},
|
||||
TypePointers{&userDefined},
|
||||
@ -3805,9 +3890,8 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
|
||||
false, /*_arbitraryParameters */
|
||||
StateMutability::Pure
|
||||
)
|
||||
);
|
||||
members.emplace_back(
|
||||
"unwrap",
|
||||
));
|
||||
members.emplace_back(magicFunc(
|
||||
TypeProvider::function(
|
||||
TypePointers{&userDefined},
|
||||
TypePointers{&userDefined.underlyingType()},
|
||||
@ -3817,13 +3901,13 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
|
||||
false, /* _arbitraryParameters */
|
||||
StateMutability::Pure
|
||||
)
|
||||
);
|
||||
));
|
||||
}
|
||||
else if (
|
||||
auto const* arrayType = dynamic_cast<ArrayType const*>(m_actualType);
|
||||
arrayType && arrayType->isByteArray()
|
||||
)
|
||||
members.emplace_back("concat", TypeProvider::function(
|
||||
members.emplace_back(magicFunc(TypeProvider::function(
|
||||
TypePointers{},
|
||||
TypePointers{TypeProvider::bytesMemory()},
|
||||
strings{},
|
||||
@ -3831,7 +3915,7 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
|
||||
FunctionType::Kind::BytesConcat,
|
||||
/* _arbitraryParameters */ true,
|
||||
StateMutability::Pure
|
||||
));
|
||||
)));
|
||||
|
||||
return members;
|
||||
}
|
||||
@ -3947,35 +4031,39 @@ bool MagicType::operator==(Type const& _other) const
|
||||
|
||||
MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
{
|
||||
auto const magicFunc = [](FunctionType const* _functionType) -> MemberList::Member {
|
||||
return {FunctionType::magicName(_functionType->kind()), _functionType};
|
||||
};
|
||||
|
||||
switch (m_kind)
|
||||
{
|
||||
case Kind::Block:
|
||||
return MemberList::MemberMap({
|
||||
{"coinbase", TypeProvider::payableAddress()},
|
||||
{"timestamp", TypeProvider::uint256()},
|
||||
{"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)},
|
||||
{"difficulty", TypeProvider::uint256()},
|
||||
{"number", TypeProvider::uint256()},
|
||||
{"gaslimit", TypeProvider::uint256()},
|
||||
{"chainid", TypeProvider::uint256()},
|
||||
{"basefee", TypeProvider::uint256()}
|
||||
{"coinbase"sv, TypeProvider::payableAddress()},
|
||||
{"timestamp"sv, TypeProvider::uint256()},
|
||||
magicFunc(TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)),
|
||||
{"difficulty"sv, TypeProvider::uint256()},
|
||||
{"number"sv, TypeProvider::uint256()},
|
||||
{"gaslimit"sv, TypeProvider::uint256()},
|
||||
{"chainid"sv, TypeProvider::uint256()},
|
||||
{"basefee"sv, TypeProvider::uint256()}
|
||||
});
|
||||
case Kind::Message:
|
||||
return MemberList::MemberMap({
|
||||
{"sender", TypeProvider::address()},
|
||||
{"gas", TypeProvider::uint256()},
|
||||
{"value", TypeProvider::uint256()},
|
||||
{"data", TypeProvider::array(DataLocation::CallData)},
|
||||
{"sig", TypeProvider::fixedBytes(4)}
|
||||
{"sender"sv, TypeProvider::address()},
|
||||
{"gas"sv, TypeProvider::uint256()},
|
||||
{"value"sv, TypeProvider::uint256()},
|
||||
{"data"sv, TypeProvider::array(DataLocation::CallData)},
|
||||
{"sig"sv, TypeProvider::fixedBytes(4)}
|
||||
});
|
||||
case Kind::Transaction:
|
||||
return MemberList::MemberMap({
|
||||
{"origin", TypeProvider::address()},
|
||||
{"gasprice", TypeProvider::uint256()}
|
||||
{"origin"sv, TypeProvider::address()},
|
||||
{"gasprice"sv, TypeProvider::uint256()}
|
||||
});
|
||||
case Kind::ABI:
|
||||
return MemberList::MemberMap({
|
||||
{"encode", TypeProvider::function(
|
||||
magicFunc(TypeProvider::function(
|
||||
TypePointers{},
|
||||
TypePointers{TypeProvider::array(DataLocation::Memory)},
|
||||
strings{},
|
||||
@ -3983,8 +4071,8 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
FunctionType::Kind::ABIEncode,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
)},
|
||||
{"encodePacked", TypeProvider::function(
|
||||
)),
|
||||
magicFunc(TypeProvider::function(
|
||||
TypePointers{},
|
||||
TypePointers{TypeProvider::array(DataLocation::Memory)},
|
||||
strings{},
|
||||
@ -3992,8 +4080,8 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
FunctionType::Kind::ABIEncodePacked,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
)},
|
||||
{"encodeWithSelector", TypeProvider::function(
|
||||
)),
|
||||
magicFunc(TypeProvider::function(
|
||||
TypePointers{TypeProvider::fixedBytes(4)},
|
||||
TypePointers{TypeProvider::array(DataLocation::Memory)},
|
||||
strings{1, ""},
|
||||
@ -4001,8 +4089,8 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
FunctionType::Kind::ABIEncodeWithSelector,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
)},
|
||||
{"encodeWithSignature", TypeProvider::function(
|
||||
)),
|
||||
magicFunc(TypeProvider::function(
|
||||
TypePointers{TypeProvider::array(DataLocation::Memory, true)},
|
||||
TypePointers{TypeProvider::array(DataLocation::Memory)},
|
||||
strings{1, ""},
|
||||
@ -4010,8 +4098,8 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
FunctionType::Kind::ABIEncodeWithSignature,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
)},
|
||||
{"decode", TypeProvider::function(
|
||||
)),
|
||||
magicFunc(TypeProvider::function(
|
||||
TypePointers(),
|
||||
TypePointers(),
|
||||
strings{},
|
||||
@ -4019,7 +4107,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
FunctionType::Kind::ABIDecode,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
)}
|
||||
))
|
||||
});
|
||||
case Kind::MetaType:
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ public:
|
||||
struct Member
|
||||
{
|
||||
/// Manual constructor for members that are not taken from a declaration.
|
||||
Member(char const* _name, Type const* _type):
|
||||
Member(std::string_view _name, Type const* _type):
|
||||
name(_name),
|
||||
type(_type),
|
||||
declaration(nullptr)
|
||||
@ -1245,6 +1245,11 @@ public:
|
||||
Declaration,
|
||||
};
|
||||
|
||||
/// Returns the magic name of this function kind, if there is any.
|
||||
///
|
||||
/// If there is no magic or native name for this function, an empty string is returned instead.
|
||||
static std::string_view magicName(Kind _kind);
|
||||
|
||||
/// Creates the type of a function.
|
||||
/// @arg _kind must be Kind::Internal, Kind::External or Kind::Declaration.
|
||||
explicit FunctionType(FunctionDefinition const& _function, Kind _kind = Kind::Declaration);
|
||||
|
@ -57,7 +57,7 @@
|
||||
"typeDescriptions":
|
||||
{
|
||||
"typeIdentifier": "t_function_error_pure$__$returns$__$",
|
||||
"typeString": "function () pure"
|
||||
"typeString": "error ()"
|
||||
}
|
||||
},
|
||||
"id": 6,
|
||||
|
@ -4,4 +4,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 6359: (82-94): Return argument type function () pure returns (bytes memory) is not implicitly convertible to expected type (type of first return variable) bytes memory.
|
||||
// TypeError 6359: (82-94): Return argument type concat() pure returns (bytes memory) is not implicitly convertible to expected type (type of first return variable) bytes memory.
|
||||
|
@ -53,7 +53,7 @@ contract C {
|
||||
// TypeError 9553: (415-428): Invalid type for argument in function call. Invalid implicit conversion from function () view external returns (uint256) to function () pure external returns (uint256) requested.
|
||||
// TypeError 9553: (465-481): Invalid type for argument in function call. Invalid implicit conversion from function () external returns (uint256) to function () pure external returns (uint256) requested.
|
||||
// TypeError 9553: (518-545): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) pure external returns (uint256) to function () pure external returns (uint256) requested.
|
||||
// TypeError 9553: (582-589): Invalid type for argument in function call. Invalid implicit conversion from function () view returns (uint256) to function () pure external returns (uint256) requested. Special functions can not be converted to function types.
|
||||
// TypeError 9553: (582-589): Invalid type for argument in function call. Invalid implicit conversion from gasleft() view returns (uint256) to function () pure external returns (uint256) requested. Special functions can not be converted to function types.
|
||||
// TypeError 9553: (626-629): Invalid type for argument in function call. Invalid implicit conversion from function () pure returns (uint256) to function () pure external returns (uint256) requested. Special functions can not be converted to function types.
|
||||
// TypeError 9553: (666-686): Invalid type for argument in function call. Invalid implicit conversion from function () pure returns (uint256) to function () pure external returns (uint256) requested. Special functions can not be converted to function types.
|
||||
// TypeError 9582: (723-748): Member "testInternalFunction" not found or not visible after argument-dependent lookup in contract C.
|
||||
|
@ -9,4 +9,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9582: (133-136): Member "f" not found or not visible after argument-dependent lookup in function (uint256) pure.
|
||||
// TypeError 9582: (133-136): Member "f" not found or not visible after argument-dependent lookup in error E(uint256).
|
||||
|
@ -4,4 +4,4 @@ contract C {
|
||||
function() internal pure x = E;
|
||||
}
|
||||
// ----
|
||||
// TypeError 7407: (58-59): Type function () pure is not implicitly convertible to expected type function () pure. Special functions can not be converted to function types.
|
||||
// TypeError 7407: (58-59): Type error E() is not implicitly convertible to expected type function () pure. Special functions can not be converted to function types.
|
||||
|
@ -4,4 +4,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9574: (42-103): Type function (uint256) view returns (bytes32) is not implicitly convertible to expected type function (uint256) view returns (bytes32). Special functions can not be converted to function types.
|
||||
// TypeError 9574: (42-103): Type blockhash(uint256) view returns (bytes32) is not implicitly convertible to expected type function (uint256) view returns (bytes32). Special functions can not be converted to function types.
|
||||
|
@ -0,0 +1,9 @@
|
||||
contract C {
|
||||
event That(uint a);
|
||||
function f() public {
|
||||
function (uint) pure g = That;
|
||||
emit That(2);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9574: (71-100): Type event That(uint256) is not implicitly convertible to expected type function (uint256) pure. Special functions can not be converted to function types.
|
@ -4,4 +4,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9582: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32).
|
||||
// TypeError 9582: (47-60): Member "gas" not found or not visible after argument-dependent lookup in keccak256(bytes memory) pure returns (bytes32).
|
||||
|
@ -4,4 +4,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9582: (47-57): Member "gas" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32).
|
||||
// TypeError 9582: (47-57): Member "gas" not found or not visible after argument-dependent lookup in sha256(bytes memory) pure returns (bytes32).
|
||||
|
@ -4,4 +4,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9582: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes20).
|
||||
// TypeError 9582: (47-60): Member "gas" not found or not visible after argument-dependent lookup in ripemd160(bytes memory) pure returns (bytes20).
|
||||
|
@ -4,4 +4,4 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9582: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function (bytes32,uint8,bytes32,bytes32) pure returns (address).
|
||||
// TypeError 9582: (47-60): Member "gas" not found or not visible after argument-dependent lookup in ecrecover(bytes32,uint8,bytes32,bytes32) pure returns (address).
|
||||
|
@ -4,5 +4,5 @@ function test() pure {
|
||||
function (int) returns (MyInt) g = MyInt.wrap;
|
||||
}
|
||||
// ----
|
||||
// TypeError 9574: (46-93): Type function (MyInt) pure returns (int256) is not implicitly convertible to expected type function (MyInt) returns (int256). Special functions can not be converted to function types.
|
||||
// TypeError 9574: (99-144): Type function (int256) pure returns (MyInt) is not implicitly convertible to expected type function (int256) returns (MyInt). Special functions can not be converted to function types.
|
||||
// TypeError 9574: (46-93): Type unwrap(MyInt) pure returns (int256) is not implicitly convertible to expected type function (MyInt) returns (int256). Special functions can not be converted to function types.
|
||||
// TypeError 9574: (99-144): Type wrap(int256) pure returns (MyInt) is not implicitly convertible to expected type function (int256) returns (MyInt). Special functions can not be converted to function types.
|
||||
|
Loading…
Reference in New Issue
Block a user