diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index c4d4c9fd4..78a504ddc 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2924,7 +2924,10 @@ vector> FunctionType::makeStackItems() const { case Kind::External: case Kind::DelegateCall: - slots = {make_tuple("address", TypeProvider::address()), make_tuple("functionIdentifier", TypeProvider::fixedBytes(4))}; + slots = { + make_tuple("address", TypeProvider::address()), + make_tuple("functionIdentifier", TypeProvider::uint(32)) + }; break; case Kind::BareCall: case Kind::BareCallCode: diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 38d16eb69..b40768be2 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -800,11 +800,19 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) case Type::Category::Function: if (member == "selector") { - solUnimplementedAssert(false, ""); + solUnimplementedAssert( + dynamic_cast(*_memberAccess.expression().annotation().type).kind() == + FunctionType::Kind::External, "" + ); + define(IRVariable{_memberAccess}, IRVariable(_memberAccess.expression()).part("functionIdentifier")); } else if (member == "address") { - solUnimplementedAssert(false, ""); + solUnimplementedAssert( + dynamic_cast(*_memberAccess.expression().annotation().type).kind() == + FunctionType::Kind::External, "" + ); + define(IRVariable{_memberAccess}, IRVariable(_memberAccess.expression()).part("address")); } else solAssert( diff --git a/test/libsolidity/semanticTests/viaYul/function_address.sol b/test/libsolidity/semanticTests/viaYul/function_address.sol new file mode 100644 index 000000000..402ad1481 --- /dev/null +++ b/test/libsolidity/semanticTests/viaYul/function_address.sol @@ -0,0 +1,17 @@ +contract C { + function f() external returns (address) { + return this.f.address; + } + function g() external returns (bool) { + return this.f.address == address(this); + } + function h(function() external a) public returns (address) { + return a.address; + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 0x0fdd67305928fcac8d213d1e47bfa6165cd0b87b +// g() -> true +// h(function): left(0x1122334400112233445566778899AABBCCDDEEFF42424242) -> 0x1122334400112233445566778899AABBCCDDEEFF diff --git a/test/libsolidity/semanticTests/viaYul/function_selector.sol b/test/libsolidity/semanticTests/viaYul/function_selector.sol new file mode 100644 index 000000000..40faef1dd --- /dev/null +++ b/test/libsolidity/semanticTests/viaYul/function_selector.sol @@ -0,0 +1,13 @@ +contract C { + function f() external returns (bytes4) { + return this.f.selector; + } + function h(function() external a) public returns (bytes4) { + return a.selector; + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> left(0x26121ff0) +// h(function): left(0x1122334400112233445566778899AABBCCDDEEFF42424242) -> left(0x42424242)